home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / Pascal / Applications / NIH Image 1.62b11 / src / Image.p < prev    next >
Text File  |  1997-05-05  |  75KB  |  2,835 lines

  1. program Image;
  2.  
  3. {NIH Image is a public domain program for the Macintosh for acquiring, }
  4. {processing, analyzing, editing, printing, and animating 8-bit images.}
  5.  
  6.  
  7. {Version 1.62, 27 Feb 1996}
  8.  
  9.  
  10. {Developed using Metrowerks CodeWarrior CW11 PPC and 68K Pascal compilers.}
  11.  
  12. {Author :}
  13. {Wayne Rasband}
  14. {National Institutes of Health}
  15.  
  16. {email: wayne@codon.nih.gov}
  17. {WWW: http://rsb.info.nih.gov/nih-image/}
  18. {Anonymous FTP: zippy.nimh.nih.gov}
  19.  
  20.  
  21.     uses
  22.         Types, Memory, QuickDraw, QuickDrawText, Packages, Menus, Events, Fonts, 
  23.         Scrap, ToolUtils, Resources, Errors, Palettes, StandardFile, Windows, OSUtils,
  24.         Controls, TextEdit, Files, Dialogs, TextUtils, Finder, MixedMode, Processes,
  25.         Devices, Balloons, AppleEvents, DiskInit, EPPC, SegLoad,
  26.         Globals, Utilities, Init, File1, File2, Analysis, Graphics, 
  27.         Edit, Filters, Camera, User, Macros1, Macros2, Stacks, Background,
  28.         Lut, Projection, Plugins, Text, Math, Registration, {Profiler,} fft, Edm;
  29.  
  30.  
  31. {Turn off automatic toolbox initialization.}
  32. {$I-}
  33.  
  34.  
  35. {PROCEDURE MacsBug; inline $a9ff;}
  36.  
  37.  
  38.     procedure UpdateOptionsMenu;
  39.         var
  40.             CheckIt: boolean;
  41.             i: integer;
  42.     begin
  43.         with info^ do begin
  44.                 CheckItem(OptionsMenuH, GrayscaleItem, (LutMode = Grayscale) or (LutMode = CustomGrayscale));
  45.                 if LutMode <> PseudoColor then
  46.                     ColorTable := CustomTable;
  47.                 CheckItem(ColorTablesMenuH, SystemPaletteItem, ColorTable = AppleDefault);
  48.                 CheckItem(ColorTablesMenuH, Pseudo20Item, ColorTable = Pseudo20);
  49.                 CheckItem(ColorTablesMenuH, Pseudo32Item, ColorTable = Pseudo32);
  50.                 CheckItem(ColorTablesMenuH, RainbowItem, ColorTable = Rainbow);
  51.                 CheckItem(ColorTablesMenuH, Fire1Item, ColorTable = Fire1);
  52.                 CheckItem(ColorTablesMenuH, Fire2Item, ColorTable = Fire2);
  53.                 CheckItem(ColorTablesMenuH, IceItem, ColorTable = Ice);
  54.                 CheckItem(ColorTablesMenuH, GraysItem, ColorTable = Grays);
  55.                 CheckItem(ColorTablesMenuH, SpectrumItem, ColorTable = Spectrum);
  56.                 SetMenuItem(OptionsMenuH, ScaleToFitItem, info <> NoInfo);
  57.                 CheckIt := ScaleToFitWindow;
  58.                 CheckItem(OptionsMenuH, ScaleToFitItem, CheckIt);
  59.                 CheckItem(OptionsMenuH, ThresholdItem, Thresholding);
  60.                 CheckItem(OptionsMenuH, SliceItem, DensitySlicing);
  61.                 SetMenuItem(OptionsMenuH, PropagateItem, nPics > 1);
  62.             end;
  63.     end;
  64.  
  65.  
  66.     procedure UpdateProcessMenu;
  67.         var
  68.             ShowItems: boolean;
  69.             i: integer;
  70.             str: str255;
  71.     begin
  72.         ShowItems := Info <> NoInfo;
  73.         for i := SmoothItem to FilterItem do
  74.             SetMenuItem(ProcessMenuH, i, ShowItems);
  75.         with info^ do
  76.             if (LutMode = GrayScale) or (LutMode = CustomGrayscale) or DensitySlicing then
  77.                 SetMenuItemText(ProcessMenuH, ApplyItem, 'Apply LUT')
  78.             else
  79.                 SetMenuItemText(ProcessMenuH, ApplyItem, 'Convert to Grayscale');
  80.         if CurrentWindow = TextKind then
  81.             SetMenuItemText(ProcessMenuH, ConvolveItem, 'Convolve')
  82.         else
  83.             SetMenuItemText(ProcessMenuH, ConvolveItem, 'Convolve…');
  84.         for i := BinaryItem to FixColorsItem do
  85.             SetMenuItem(ProcessMenuH, i, ShowItems);
  86.         NumToString(BinaryCount, str);
  87.         str := concat('Set Count[', str, ']…');
  88.         SetMenuItemText(BinaryMenuH, SetCountItem, str);
  89.         NumToString(BinaryIterations, str);
  90.         str := concat('Set Iterations[', str, ']…');
  91.         SetMenuItemText(BinaryMenuH, IterationsItem, str);
  92.         CheckItem(BackgroundMenuH, FasterItem, FasterBackgroundSubtraction);
  93.         NumToString(BallRadius, str);
  94.         str := concat('Set Radius[', str, ']…');
  95.         SetMenuItemText(BackgroundMenuH, RadiusItem, str);
  96.     end;
  97.  
  98.  
  99.  
  100.  
  101.     procedure UpdateSpecialMenu;
  102.         var
  103.             ShowItems: boolean;
  104.     begin
  105.         ShowItems := Info <> NoInfo;
  106.         SetMenuItem(SpecialMenuH, SaveBlankFieldItem, ShowItems);
  107.         SetMenuItem(SpecialMenuH, PhotoModeItem, ShowItems);
  108.         if CurrentWindow = TextKind then
  109.             SetMenuItemText(SpecialMenuH, LoadMacrosItem, 'Load Macros from Window')
  110.         else
  111.             SetMenuItemText(SpecialMenuH, LoadMacrosItem, 'Load Macros…')
  112.     end;
  113.  
  114.  
  115.     procedure UpdateStacksMenu;
  116.         var
  117.             ShowItems: boolean;
  118.             isStack: boolean;
  119.     begin
  120.         ShowItems := Info <> NoInfo;
  121.         SetMenuItem(StacksMenuH, StackFromWindowsItem, nPics > 0);
  122.         isStack := info^.StackInfo <> nil;
  123.         SetMenuItem(StacksMenuH, WindowsFromStackItem, isStack);
  124.         SetMenuItem(StacksMenuH, AddSliceItem, isStack);
  125.         SetMenuItem(StacksMenuH, DeleteSliceItem, isStack);
  126.         SetMenuItem(StacksMenuH, NextSliceItem, isStack);
  127.         SetMenuItem(StacksMenuH, PreviousSliceItem, isStack);
  128.         SetMenuItem(StacksMenuH, MakeMovieItem, ShowItems);
  129.         SetMenuItem(StacksMenuH, CaptureFramesItem, ShowItems);
  130.         SetMenuItem(StacksMenuH, AnimateItem, isStack);
  131.         SetMenuItem(StacksMenuH, AverageSlicesItem, isStack);
  132.         SetMenuItem(StacksMenuH, MakeMontageItem, isStack);
  133.         SetMenuItem(StacksMenuH, RegisterItem, isStack);
  134.         SetMenuItem(StacksMenuH, CaptureColorItem, ShowItems);
  135.         SetMenuItem(StacksMenuH, RGBToColorItem, isStack);
  136.         SetMenuItem(StacksMenuH, ColorToRGBItem, ShowItems and (not isStack));
  137.         SetMenuItem(StacksMenuH, RGBToHSVItem, isStack);
  138.         SetMenuItem(StacksMenuH, ProjectItem, isStack);
  139.         SetMenuItem(StacksMenuH, ResliceItem, isStack);
  140.         SetMenuItem(StacksMenuH, StackInfoItem, isStack);
  141.     end;
  142.  
  143.  
  144.     function AboutFilter (d: DialogPtr; var event: EventRecord; var ItemHit: integer): boolean;
  145. { simple filter proc for about box -- must be at top level! % }
  146.     begin
  147.         if (event.what in [MouseDown, KeyDown, AutoKey]) then begin
  148.                 AboutFilter := true;
  149.                 ItemHit := OK;
  150.             end
  151.         else begin
  152.                 AboutFilter := false;
  153.                 ItemHit := 0;
  154.             end;
  155.     end;
  156.  
  157.  
  158.     procedure AboutUProc (d: DialogPtr; item: integer);
  159. { About box user proc -- must be at top level!}
  160.         var
  161.             s: str255;
  162.             saveport: grafptr;
  163.             VersInfo: str255;
  164.     begin
  165.         getport(saveport);
  166.         setport(d);
  167.         if (item = MemItem) then begin
  168.                 NumToString(FreeMem div 1024, s);
  169.                 s := concat(s, 'K free');
  170.                 DrawSItem(MemItem, Geneva, 9, d, s);
  171.             end
  172.         else if (item = VersItem) then begin
  173.                 RealToString(version / 100.0, 4, 2, VersInfo);
  174.                 VersInfo := concat('Version ', VersInfo);
  175.                 DrawSItem(VersItem, Geneva, 9, d, VersInfo);
  176.             end;
  177.         setport(saveport);
  178.     end;
  179.  
  180.  
  181.     procedure DoAbout;
  182.   {About Box by David Powell}
  183.         var
  184.             i: integer;
  185.             d: dialogptr;
  186.             midscreen: point;
  187.             r: rect;
  188.             h: handle;
  189.             itype: integer;
  190.     begin
  191.         if AboutBoxFilterProc=nil
  192.             then AboutBoxFilterProc:=NewRoutineDescriptor(@AboutFilter, uppModalFilterProcInfo, GetCurrentISA);
  193.         if AboutBoxUserProc=nil
  194.             then AboutBoxUserProc:=NewRoutineDescriptor(@AboutUProc, uppUserItemProcInfo, GetCurrentISA);
  195.         d := getnewdialog(AboutID, nil, pointer(-1));
  196.         if (d <> nil) then begin
  197.                 SetPort(d);
  198.                 GetDialogItem(d, VersItem, itype, h, r);
  199.                 SetDialogItem(d, VersItem, itype, handle(AboutBoxUserProc), r);
  200.                 GetDialogItem(d, MemItem, itype, h, r);
  201.                 SetDialogItem(d, MemItem, itype, handle(AboutBoxUserProc), r);
  202.                 ShowWindow(d);
  203.                 repeat
  204.                     ModalDialog(AboutBoxFilterProc, i);
  205.                 until (i = OK);
  206.                 DisposeDialog(d);
  207.                 FlushEvents(EveryEvent, 0);
  208.             end;
  209.     end;
  210.  
  211.  
  212.     procedure DoPreferences;
  213.         const
  214.             BufferSizeID = 7;
  215.             CreatorID = 8;
  216.             ScaleConvolutionsID = 9;
  217.             InvertValuesID =10;
  218.             InvertYID = 11;
  219.             SwitchingID = 12;
  220.             HighlightID = 13;
  221.             OscillatingID = 14;
  222.             FriendlyID = 15;
  223.         var
  224.             mylog: DialogPtr;
  225.             item, i: integer;
  226.             SaveScaleC: boolean;
  227.             SaveInvertValues, SaveInvertY, SaveMovies, NewFriendlyMode, okay: boolean;
  228.             SaveBufferSize: LongInt;
  229.             SaveCreator: packed array[1..4] of char;
  230.             tCreator:str255;
  231.             SaveInfo:InfoPtr;
  232.     begin
  233.         InitCursor;
  234.         if isInvertingFunction then
  235.             InvertPixelValues:=true;
  236.         SaveBufferSize := BufferSize;
  237.         SaveInvertY := InvertYCoordinates;
  238.         SaveScaleC := ScaleConvolutions;
  239.         SaveCreator := TextCreator;
  240.         SaveMovies := OscillatingMovies;
  241.         NewfriendlyMode := LutFriendlyMode;
  242.         mylog := GetNewDialog(6000, nil, pointer(-1));
  243.         SetDNum(MyLog, BufferSizeID, BufferSize div 1024);
  244.         SetDlogItem(mylog, ScaleConvolutionsID, ord(ScaleConvolutions));
  245.         SetDlogItem(mylog, InvertYID, ord(InvertYCoordinates));
  246.         SetDlogItem(mylog, SwitchingID, ord(SwitchLUTOnSuspend));
  247.         SetDlogItem(mylog, HighlightID, ord(HighlightMode));
  248.         SetDlogItem(mylog, OscillatingID, ord(OscillatingMovies));
  249.         SetDlogItem(mylog, FriendlyID, ord(LutFriendlyMode));
  250.         SaveInvertValues := InvertPixelValues;
  251.         if InvertPixelValues then
  252.             SetDlogItem(mylog, InvertValuesID, 1);
  253.         tCreator:='1234';
  254.         tCreator[1]:=TextCreator[1];
  255.         tCreator[2]:=TextCreator[2];
  256.         tCreator[3]:=TextCreator[3];
  257.         tCreator[4]:=TextCreator[4];
  258.         SetDString(mylog, CreatorID, tCreator);
  259.         repeat
  260.             ModalDialog(nil, item);
  261.             if item = BufferSizeID then begin
  262.                     BufferSize := GetDNum(MyLog, BufferSizeID) * 1024;
  263.                     if BufferSize < 1 then begin
  264.                             beep;
  265.                             BufferSize := 1;
  266.                             SetDNum(MyLog, BufferSizeID, BufferSize);
  267.                         end;
  268.                 end;
  269.             if item = ScaleConvolutionsID then begin
  270.                     ScaleConvolutions := not ScaleConvolutions;
  271.                     SetDlogItem(mylog, ScaleConvolutionsID, ord(ScaleConvolutions));
  272.                 end;
  273.             if item = InvertValuesID then begin
  274.                     InvertPixelValues := not InvertPixelValues;
  275.                     SetDlogItem(mylog, InvertValuesID, ord(InvertPixelValues));
  276.                 end;
  277.             if item = InvertYID then begin
  278.                     InvertYCoordinates := not InvertYCoordinates;
  279.                     SetDlogItem(mylog, InvertYID, ord(InvertYCoordinates));
  280.                 end;
  281.             if item = SwitchingID then begin
  282.                     SwitchLUTOnSuspend := not SwitchLUTOnSuspend;
  283.                     SetDlogItem(mylog, SwitchingID, ord(SwitchLUTOnSuspend));
  284.                 end;
  285.             if item = HighlightID then begin
  286.                     HighlightMode := not HighlightMode;
  287.                     SetDlogItem(mylog, HighlightID, ord(HighlightMode));
  288.                     LoadLUT(info^.ctable);
  289.                 end;
  290.             if item = CreatorID then begin
  291.                 tCreator := GetDString(mylog, item);
  292.                 if length(tCreator)=4 then begin 
  293.                     TextCreator[1]:=tCreator[1];
  294.                     TextCreator[2]:=tCreator[2];
  295.                     TextCreator[3]:=tCreator[3];
  296.                     TextCreator[4]:=tCreator[4];
  297.                 end;
  298.             end;
  299.             if item = OscillatingID then begin
  300.                     OscillatingMovies := not OscillatingMovies;
  301.                     SetDlogItem(mylog, OscillatingID, ord(OscillatingMovies));
  302.                 end;
  303.             if item = FriendlyID then begin
  304.                     NewFriendlyMode := not NewFriendlyMode;
  305.                     SetDlogItem(mylog, FriendlyID, ord(NewFriendlyMode));
  306.                 end;
  307.         until (item = ok) or (item = cancel);
  308.         DisposeDialog(mylog);
  309.         if item = cancel then begin
  310.                 BufferSize := SaveBufferSize;
  311.                 ScaleConvolutions := SaveScaleC;
  312.                 InvertYCoordinates := SaveInvertY;
  313.                 OscillatingMovies := SaveMovies;
  314.                 if PasteControl <> nil then
  315.                     DrawPasteControl;
  316.                 TextCreator := SaveCreator;
  317.             end
  318.         else
  319.             with info^ do begin
  320.                     if InvertPixelValues then begin
  321.                         SaveInfo:=info;
  322.                         for i := 1 to nPics do begin
  323.                                 Info := pointer(WindowPeek(PicWindow[i])^.RefCon);
  324.                                 if info^.fit=uncalibrated then
  325.                                     InvertGrayLevels
  326.                             end; {for}
  327.                         info:=SaveInfo;
  328.                     end else if (InvertPixelValues = false) and SaveInvertValues then begin
  329.                         SaveInfo:=info;
  330.                         for i := 1 to nPics do begin
  331.                                 Info := pointer(WindowPeek(PicWindow[i])^.RefCon);
  332.                                 if isInvertingFunction then
  333.                                     RemoveDensityCalibration;
  334.                             end; {for}
  335.                         info:=SaveInfo;
  336.                     end;
  337.                 end;
  338.         if BufferSize <> SaveBufferSIze then begin
  339.                 PutError('You must quit and restart NIH Image before the Undo and Clipboard buffer size change will take effect.');
  340.                 SaveSettings;
  341.             end;
  342.         if (NewFriendlyMode <> LutFriendlyMode) then begin
  343.             if (not LutFriendlyMode) and (ScreenDepth = 8) then begin
  344.                 SaveInfo := Info;
  345.                 Info := noInfo;
  346.                 okay := LoadCLUTResource(AppleDefaultCLUT);
  347.                 Info := SaveInfo;
  348.             end;
  349.             LutFriendlyMode := NewFriendlyMode;
  350.             if ScreenDepth <= 8 then
  351.                 RestoreScreen;
  352.             UpdateLUT;
  353.         end;
  354.     end;
  355.  
  356.  
  357.     procedure UpdateWindowsMenu;
  358.         var
  359.             i, n: integer;
  360.     begin
  361.         for i := NextImageItem to TileImagesItem do
  362.             SetMenuItem(WindowsMenuH, i, nPics > 1);
  363.         for i := SelectToolsItem to SelectResultsItem do
  364.             CheckItem(WindowsMenuH, i, false);
  365.         SetMenuItem(WindowsMenuH, SelectHistogramItem, HistoWindow <> nil);
  366.         SetMenuItem(WindowsMenuH, SelectPlotItem, PlotWindow <> nil);
  367.         SetMenuItem(WindowsMenuH, SelectResultsItem, ResultsWindow <> nil);
  368.         for i := 1 to nTextWindows do
  369.             CheckItem(WindowsMenuH, WindowsMenuItems - 1 + i, false);
  370.         for i := 1 to nPics do
  371.             CheckItem(WindowsMenuH, WindowsMenuItems + nTextWindows + i, false);
  372.         if PasteControl = nil then
  373.             SetMenuItemText(WindowsMenuH, PasteControlItem, 'Show Paste Control')
  374.         else
  375.             SetMenuItemText(WindowsMenuH, PasteControlItem, 'Hide Paste Control');
  376.         if CurrentKind < 0 then
  377.             exit(UpdateWindowsMenu); {System Window}
  378.         case CurrentKind of
  379.             ToolKind: 
  380.                 CheckItem(WindowsMenuH, SelectToolsItem, true);
  381.             MapKind: 
  382.                 CheckItem(WindowsMenuH, SelectGrayMapItem, true);
  383.             LUTKind: 
  384.                 CheckItem(WindowsMenuH, SelectLutItem, true);
  385.             InfoKind: 
  386.                 CheckItem(WindowsMenuH, SelectInfoItem, true);
  387.             HistoKind: 
  388.                 CheckItem(WindowsMenuH, SelectHistogramItem, true);
  389.             ProfilePlotKind, CalibrationPLotKind: 
  390.                 CheckItem(WindowsMenuH, SelectPlotItem, true);
  391.             ResultsKind: 
  392.                 CheckItem(WindowsMenuH, SelectResultsItem, true);
  393.             TextKind:  begin
  394.                     if TextInfo <> nil then
  395.                         CheckItem(WindowsMenuH, WindowsMenuItems - 1 + TextInfo^.WindowNum, true);
  396.                 end;
  397.             PicKind: 
  398.                 CheckItem(WindowsMenuH, WindowsMenuItems + nTextWindows + info^.PicNum, true);
  399.             otherwise
  400.         end;
  401.     end;
  402.  
  403.  
  404.  
  405.  
  406.     procedure CloseAll;
  407.     FORWARD;
  408.  
  409.  
  410.     procedure DoNew;
  411.         const
  412.             ImageID = 4;
  413.             TextID = 5;
  414.             WidthID = 6;
  415.             HeightID = 7;
  416.             TitleID = 8;
  417.         var
  418.             mylog: DialogPtr;
  419.             item, i: integer;
  420.             SaveWidth, SaveHeight: integer;
  421.             SaveTitle: string[31];
  422.             okay, OpenImage: boolean;
  423.  
  424.         procedure SetButtons;
  425.         begin
  426.             SetDlogItem(mylog, ImageID, ord(OpenImage));
  427.             SetDlogItem(mylog, TextID, ord(not OpenImage));
  428.         end;
  429.  
  430.     begin
  431.         InitCursor;
  432.         OpenImage := true;
  433.         SaveWidth := NewPicWidth;
  434.         SaveHeight := NewPicHeight;
  435.         SaveTitle := NewTitle;
  436.         mylog := GetNewDialog(180, nil, pointer(-1));
  437.         SetButtons;
  438.         SetDNum(MyLog, WidthID, NewPicWidth);
  439.         SelectdialogItemText(MyLog, WidthID, 0, 32767);
  440.         SetDNum(MyLog, HeightID, NewPicHeight);
  441.         SetDString(MyLog, TitleID, NewTitle);
  442.         repeat
  443.             ModalDialog(nil, item);
  444.             if item = ImageID then begin
  445.                     OpenImage := true;
  446.                     SetButtons;
  447.                 end;
  448.             if item = TextID then begin
  449.                     OpenImage := false;
  450.                     SetButtons;
  451.                 end;
  452.             if item = WidthID then begin
  453.                     NewPicWidth := GetDNum(MyLog, WidthID);
  454.                     if (NewPicWidth < 0) or (NewPicWidth > MaxPicSize) then begin
  455.                             NewPicWidth := SaveWidth;
  456.                             SetDNum(MyLog, WidthID, NewPicWidth);
  457.                         end;
  458.                 end;
  459.             if item = HeightID then begin
  460.                     NewPicHeight := GetDNum(MyLog, HeightID);
  461.                     if (NewPicHeight < 0) or (NewPicHeight > MaxPicSize) then begin
  462.                             NewPicHeight := SaveHeight;
  463.                             SetDNum(MyLog, HeightID, NewPicHeight);
  464.                         end;
  465.                 end;
  466.         until (item = ok) or (item = cancel);
  467.         if item = ok then
  468.             NewTitle := GetDString(MyLog, TitleID);
  469.         DisposeDialog(mylog);
  470.         if NewPicWidth < 32 then
  471.             NewPicWidth := 32;
  472.         if NewPicHeight < 1 then
  473.             NewPicHeight := 1;
  474.         if item = cancel then begin
  475.                 NewPicWidth := SaveWidth;
  476.                 NewPicHeight := SaveHeight;
  477.                 NewTitle := SaveTitle;
  478.                 exit(DoNew);
  479.             end;
  480.         if OpenImage then begin
  481.                 okay := NewPicWindow(NewTitle, NewPicWidth, NewPicHeight);
  482.                 if okay then
  483.                     if info^.PixMapSize > UndoBufSize then
  484.                         PutWarning;
  485.             end
  486.         else
  487.             okay := MakeNewTextWindow(NewTitle, 500, 400);
  488.     end;
  489.  
  490.  
  491.     procedure DoMenuEvent (MenuChoice: LongInt);
  492.         var
  493.             MenuID, MenuItem, i, ignore: integer;
  494.             name, str: str255;
  495.             dna, RefNum: integer;
  496.             ItemName: str255;
  497.             FontName: str255;
  498.             ok, isSelection: boolean;
  499.             NewStyle: StyleItem;
  500.             t: FateTable;  {Only needed for MakeSkeleton}
  501.             SaveBFInfo: InfoPtr;
  502.             err: OSErr;
  503.     begin
  504.         MenuID := HiWrd(MenuChoice);
  505.         MenuItem := LoWrd(MenuChoice);
  506.         case MenuID of
  507.  
  508.             AppleMenu:  begin
  509.                     if MenuItem = 1 then
  510.                         DoAbout
  511.                     else begin
  512.                             GetMenuItemText(GetMenuHandle(AppleMenu), MenuItem, name);
  513.                             ignore := OpenDeskAcc(name)
  514.                         end;
  515.                 end;
  516.  
  517.             FileMenu:  begin
  518.                     StopDigitizing;
  519.                     isInsertionPoint := false;
  520.                     case MenuItem of
  521.                         NewItem:
  522.                             DoNew;
  523.                         OpenItem:
  524.                             ok := DoOpen('', 0);
  525.                         ImportItem:
  526.                             ok := ImportFile('', 0);
  527.             {-}
  528.                         CloseItem: 
  529.                             if OptionKeyWasDown and (CurrentWindow <> TextKInd) then
  530.                                 CloseAll
  531.                             else
  532.                                 DoClose;
  533.                         SaveItem: 
  534.                             if OptionKeyWasDown and (info^.StackInfo = nil) and (CurrentWindow <> TextKind) then
  535.                                 SaveAll
  536.                             else
  537.                                 SaveFile;
  538.                         SaveAsItem: 
  539.                             case CurrentWindow of
  540.                                 TextKind: 
  541.                                     SaveTextAs;
  542.                                 ResultsKind: 
  543.                                     Export('', 0);
  544.                                 otherwise
  545.                                     SaveAs('', 0);
  546.                             end;
  547.                         ExportItem: 
  548.                             Export('', 0);
  549.            {-}
  550.                         RecordPreferencesItem: 
  551.                             SaveSettings;
  552.                         RevertItem: 
  553.                             with info^ do
  554.                                 if DataType = EightBits then
  555.                                     RevertToSaved
  556.                                 else
  557.                                     RescaleToEightBits;
  558.                         DuplicateItem: 
  559.                             ok := Duplicate('', false);
  560.                         GetInfoItem: 
  561.                             GetInfo;
  562.        {-}
  563.                         PageSetupItem: 
  564.                             if OptionKeyDown then
  565.                                 SetHalftone
  566.                             else
  567.                                 DoPageSetup;
  568.                         PrintItem: 
  569.                             Print(true);
  570.        {-}
  571.                         QuitItem: 
  572.                             finished := true;
  573.                     end;
  574.                     if OpeningRGB then begin
  575.                         ConvertRGBToEightBitColor(true);
  576.                         OpeningRGB := false;
  577.                     end;
  578.                 end;
  579.  
  580.             AcquireMenu: 
  581.                 RunAcqPlugIn(MenuItem);
  582.  
  583.             ExportMenu: 
  584.                 RunExportPlugIn(MenuItem);
  585.  
  586.             EditMenu:  begin
  587.                     StopDigitizing;
  588.                     GetMenuItemText(GetMenuHandle(EditMenu), MenuItem, ItemName);
  589.                     if not SystemEdit(MenuItem - 1) then
  590.                         case MenuItem of
  591.                             UndoItem: 
  592.                                 DoUndo;
  593.              {-}
  594.                             CutItem: 
  595.                                 DoCut;
  596.                             CopyItem: 
  597.                                 DoCopy;
  598.                             PasteItem: 
  599.                                 DoPaste;
  600.                             ClearItem: 
  601.                                 DoClear;
  602.             {-}
  603.                             FillItem: 
  604.                                 if CurrentWindow = TextKind then
  605.                                     DoFind
  606.                                 else
  607.                                     SetupOperation(FillItem);
  608.                             InvertItem, DrawBoundaryItem: 
  609.                                 SetupOperation(MenuItem);
  610.                             DrawScaleItem: 
  611.                                 DrawScale;
  612.              {-}
  613.                             SelectAllItem: 
  614.                                 with info^ do
  615.                                     if CurrentWindow = TextKind then
  616.                                         SelectAllText
  617.                                     else if RoiShowing and EqualRect(RoiRect, PicRect) then
  618.                                         KillRoi
  619.                                     else
  620.                                         SelectAll(true);
  621.                             DeselectItem:
  622.                                 KillRoi;
  623.                             ScaleAndRotateItem: 
  624.                                 ScaleAndRotate;
  625.               {-}
  626.                             RotateLeftItem: 
  627.                                 Rotate(RotateLeft);
  628.                             RotateRightItem: 
  629.                                 Rotate(RotateRight);
  630.                             FlipVerticalItem: 
  631.                                 FlipOrRotate(FlipVertical);
  632.                             FlipHorizontalItem: 
  633.                                 FlipOrRotate(FlipHorizontal);
  634.               {-}
  635.                             UnzoomItem: 
  636.                                 Unzoom;
  637.                             ShowClipboardItem: 
  638.                                 ShowClipboard;
  639.                         end;
  640.                 end;
  641.  
  642.             OptionsMenu:  begin
  643.                     case MenuItem of
  644.                         GrayscaleItem: 
  645.                             ResetGrayMap;
  646.                         LutOptionsItem: 
  647.                             DoLutOptions;
  648.            {-}
  649.                         PreferencesItem: 
  650.                             DoPreferences;
  651.                         PlotOptionsItem: 
  652.                             DoProfilePlotOptions;
  653.                         ScaleToFitItem: 
  654.                             ScaleToFit;
  655.                         ThresholdItem:  begin
  656.                                 if DensitySlicing then
  657.                                     DisableDensitySlice;
  658.                                 if Info^.Thresholding then
  659.                                     DisableThresholding
  660.                                 else begin
  661.                                         SetupLutUndo;
  662.                                         AutoThreshold;
  663.                                     end;
  664.                             end;
  665.                         SliceItem: 
  666.                             if DensitySlicing then
  667.                                 DisableDensitySlice
  668.                             else begin
  669.                                     if info^.thresholding then
  670.                                         DisableThresholding;
  671.                                     EnableDensitySlice;
  672.                                 end;
  673.                     end;
  674.                 end;
  675.  
  676.             ColorTablesMenu: 
  677.                 SwitchColorTables(MenuItem, true);
  678.  
  679.             FontMenu:  begin
  680.                     GetMenuItemText(FontMenuH, MenuItem, FontName);
  681.                     GetFNum(FontName, CurrentFontID);
  682.                     DisplayText(true);
  683.                     if CurrentWindow = TextKind then
  684.                         ChangeFontOrSize;
  685.                 end;
  686.  
  687.             SizeMenu:  begin
  688.                     case MenuItem of
  689.                         1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12: 
  690.                             CurrentSize := GetFontSize(MenuItem);
  691.                     end;
  692.                     DisplayText(true);
  693.                     if IsInsertionPoint then
  694.                         UpdatePicWindow;
  695.                     if CurrentWindow = TextKind then
  696.                         ChangeFontOrSize;
  697.                 end;
  698.  
  699.             StyleMenu:  begin
  700.                     case MenuItem of
  701.                         1: 
  702.                             CurrentStyle := [];
  703.                         2, 3, 4, 5, 6:  begin
  704.                                 case MenuItem of
  705.                                     TxBold: 
  706.                                         NewStyle := Bold;
  707.                                     TxItalic: 
  708.                                         NewStyle := Italic;
  709.                                     TxUnderLine: 
  710.                                         NewStyle := Underline;
  711.                                     TxOutLine: 
  712.                                         NewStyle := Outline;
  713.                                     TxShadow: 
  714.                                         NewStyle := Shadow;
  715.                                 end;
  716.                                 if NewStyle in CurrentStyle then
  717.                                     CurrentStyle := CurrentStyle - [NewStyle]
  718.                                 else
  719.                                     CurrentStyle := CurrentStyle + [NewStyle];
  720.                             end;
  721.                         LeftItem: 
  722.                             TextJust := teJustLeft;
  723.                         CenterItem: 
  724.                             TextJust := teJustCenter;
  725.                         RightItem: 
  726.                             TextJust := teJustRight;
  727.                         NoBackgroundItem: 
  728.                             TextBack := NoBack;
  729.                         WithBackgroundItem: 
  730.                             TextBack := WithBack;
  731.                     end; {case}
  732.                     DisplayText(true);
  733.                 end;
  734.  
  735.             PropagateMenu: 
  736.                 DoPropagate(MenuItem);
  737.  
  738.             ProcessMenu:  begin
  739.                     StopDigitizing;
  740.                     SetupUndo;
  741.                     case MenuItem of
  742.                         SmoothItem: 
  743.                             if OptionKeyDown then
  744.                                 Filter(UnweightedAvg, 0, t)
  745.                             else
  746.                                 Filter(WeightedAvg, 0, t);
  747.                         SharpenItem: 
  748.                             Filter(fsharpen, 0, t);
  749.                         ShadowItem:
  750.                           DoShadowFilter; 
  751.                         FindEdgesItem: 
  752.                             Filter(FindEdges, 0, t);
  753.                         RankItem: 
  754.                             DoRankFilter;
  755.                         DitherItem: 
  756.                             Filter(Dither, 0, t);
  757.                         ConvolveItem: 
  758.                             if CurrentWindow = TextKind then
  759.                                 ConvolveUsingText
  760.                             else
  761.                                 Convolve('', 0);
  762.            {-}
  763.                         ImageMathItem: 
  764.                             DoImageMath;
  765.                         ApplyItem: 
  766.                             if CheckCalibration then
  767.                                 ApplyLookupTable;
  768.                         EnhanceItem: 
  769.                             EnhanceContrast;
  770.                         EqualizeItem: 
  771.                             EqualizeHistogram;
  772.                         FixColorsItem:
  773.                             if not isBinaryImage then
  774.                                 FixColors;
  775.                         end;
  776.                 end;
  777.  
  778.             FilterMenu: 
  779.                 RunFilterPlugin(menuItem);
  780.  
  781.             BinaryMenu: 
  782.                 case MenuItem of
  783.                     MakeBinaryItem: 
  784.                         MakeBinary;
  785.                     ErosionItem: 
  786.                         DoErosion;
  787.                     DilationItem: 
  788.                         DoDilation;
  789.                     OpeningItem: 
  790.                         DoOpening;
  791.                     ClosingItem: 
  792.                         DoClosing;
  793.                     SetCountItem: 
  794.                         SetBinaryCount;
  795.                     IterationsItem: 
  796.                         SetIterations;
  797.                     OutlineItem: 
  798.                         filter(OutlineFilter, 0, t);
  799.                     SkeletonizeItem: 
  800.                         MakeSkeleton;
  801.                     EDMItem, UltimateItem, WatershedItem:
  802.                         MakeEDM(MenuItem);
  803.                 end;
  804.  
  805.             ArithmeticMenu: 
  806.                 DoArithmetic(MenuItem, 0);
  807.                 
  808.             fftMenu:
  809.                 case MenuItem of
  810.                     ForewardFFTItem: doFFT(ForewardFFT);
  811.                     InverseFFTItem: doFFT(InverseFFTWithMask);
  812.                     RedisplayItem: RedisplayPowerSpectrum;
  813.                     SwapItem: doSwapQuadrants;
  814.                 end;
  815.  
  816.             BackgroundMenu: 
  817.                 DoBackgroundMenuEvent(MenuItem);
  818.  
  819.             AnalyzeMenu:  begin
  820.                     if MenuItem <> HistogramItem then
  821.                         StopDigitizing;
  822.                     SetupUndo;
  823.                     case MenuItem of
  824.                         MeasureItem: 
  825.                             Measure;
  826.                         AnalyzeItem: 
  827.                             AnalyzeParticles;
  828.                         ShowItem: 
  829.                             ShowResults;
  830.                         OptionsItem: 
  831.                             DoMeasurementOptions;
  832.                         HistogramItem: 
  833.                             DoHistogram;
  834.                         PlotItem: 
  835.                             PlotDensityProfile;
  836.                         PlotSurfaceItem: 
  837.                             PlotSurface;
  838.           {-}
  839.                         SetScaleItem: 
  840.                             SetScale;
  841.                         CalibrateItem: 
  842.                             Calibrate;
  843.                         RedoItem: 
  844.                             RedoMeasurement;
  845.                         DeleteItem: 
  846.                             DeleteMeasurement;
  847.                         ResetItem: 
  848.                             ResetCounter;
  849.                         RestoreItem: 
  850.                             RestoreRoi;
  851.                         MarkItem: 
  852.                             MarkSelection(mCount);
  853.                     end;
  854.                 end;
  855.  
  856.             SpecialMenu:  begin
  857.                     case MenuItem of
  858.                         StartItem: 
  859.                             StartDigitizing;
  860.                         AverageItem: 
  861.                             AverageFrames;
  862.                         SaveBlankFieldItem:  begin
  863.                                 SaveBFInfo := BlankFieldInfo;
  864.                                 BlankFieldInfo := nil; {Prevents shading correction.}
  865.                                 StopDigitizing;
  866.                                 BlankFieldInfo := SaveBFInfo;
  867.                                 SaveBlankField;
  868.                             end;
  869.                         VideoControlItem:
  870.                             ShowVideoDialog;
  871.                         PhotoModeItem: 
  872.                             PhotoMode;
  873.                         LoadMacrosItem:  begin
  874.                                 LoadMacros;
  875.                                 {$ifc not PowerPC}
  876.                                     UnloadSeg(@LoadMacros);
  877.                                 {$endc}
  878.                             end;
  879.                         otherwise
  880.                         if MenuItem >= FirstMacroItem then
  881.                                 RunMacro(MenuItem - FirstMacroItem + 1);
  882.                         {if MenuItem >= FirstMacroItem then begin
  883.                                 if ProfilerInit(collectDetailed, bestTimeBase, 50, 25) = noErr then begin
  884.                                     RunMacro(MenuItem - FirstMacroItem + 1);
  885.                                     err := ProfilerDump('Image.prof');
  886.                                     ProfilerTerm;
  887.                                 end;
  888.                             end;}
  889.                     end;
  890.                 end;
  891.  
  892.             StacksMenu:  begin
  893.                     StopDigitizing;
  894.                     case MenuItem of
  895.                         StackFromWindowsItem: 
  896.                             MakeStack;
  897.                         WindowsFromStackItem: 
  898.                             MakeWindowsFromStack;
  899.                         AddSliceItem: 
  900.                             ok := AddSlice(true);
  901.                         DeleteSliceItem: 
  902.                             DeleteSlice;
  903.                         NextSliceItem, PreviousSliceItem: 
  904.                             ShowNextSlice(MenuItem);
  905.                         MakeMovieItem: 
  906.                             MakeMovie(true);
  907.                         CaptureFramesItem: 
  908.                             CaptureFrames;
  909.                         AnimateItem: 
  910.                             Animate;
  911.                         AverageSlicesItem: 
  912.                             AverageSlices(0, 0);
  913.                         MakeMontageItem: 
  914.                             MakeMontage;
  915.                         CaptureColorItem: 
  916.                             CaptureColor;
  917.                         RGBToColorItem: 
  918.                             ConvertRGBToEightBitColor(false);
  919.                         ColorToRGBItem: 
  920.                             ConvertEightBitColorToRGB;
  921.                         RGBToHSVItem: 
  922.                             ConvertRGBToHSV;
  923.                         RegisterItem: 
  924.                             DoRegister;
  925.                         ProjectItem: 
  926.                             Project;
  927.                         ResliceItem: 
  928.                             Reslice;
  929.                         StackInfoItem: 
  930.                             DoStackInfo;
  931.                         otherwise
  932.                             beep
  933.                     end;
  934.                 end;
  935.  
  936.             WindowsMenu:  begin
  937.                     if MenuItem <> PasteControlItem then
  938.                         StopDigitizing;
  939.                     case MenuItem of
  940.                         NextImageItem: 
  941.                             ShowNextImage;
  942.                         CascadeImagesItem: 
  943.                             CascadeImages;
  944.                         TileImagesItem: 
  945.                             TileImages;
  946.                         PasteControlItem: 
  947.                             if PasteControl = nil then
  948.                                 ShowPasteControl
  949.                             else
  950.                                 ignore := CloseAWindow(PasteControl);
  951.             {-}
  952.                         SelectToolsItem: 
  953.                             SelectWindow(ToolWindow);
  954.                         SelectGrayMapItem: 
  955.                             SelectWindow(MapWindow);
  956.                         SelectLutItem: 
  957.                             SelectWindow(LUTWindow);
  958.                         SelectInfoItem: 
  959.                             SelectWindow(InfoWindow);
  960.                         SelectHistogramItem: 
  961.                             if HistoWindow <> nil then
  962.                                 SelectWindow(HistoWindow);
  963.                         SelectPlotItem: 
  964.                             if PlotWindow <> nil then
  965.                                 SelectWindow(PlotWindow);
  966.                         SelectResultsItem: 
  967.                             if ResultsWindow <> nil then
  968.                                 SelectWindow(ResultsWindow);
  969.           {-}
  970.                         otherwise
  971.                             if MenuItem <= (WindowsMenuItems - 1 + nTextWindows) then
  972.                                 SelectWindow(TextWindow[MenuItem - (WindowsMenuItems - 1)])
  973.                             else
  974.                                 SelectWindow(PicWindow[MenuItem - (WindowsMenuItems + nTextWindows)]);
  975.                     end;
  976.                 end;
  977.  
  978.             UserMenu: 
  979.                 DoUserMenuEvent(MenuItem);
  980.             otherwise
  981.         end;
  982.         HiliteMenu(0);
  983.         RoiUpdateTime := 0;
  984.     end;
  985.  
  986.  
  987.     procedure DoFreehand;
  988.         var
  989.             finish: point;
  990.             event: EventRecord;
  991.             wright, wbottom: integer;
  992.             b: boolean;
  993.     begin
  994.         SetPort(info^.wptr);
  995.         PenPat(AntPattern[PatIndex]);
  996.         PenSize(1, 1);
  997.         with info^.wptr^.PortRect do begin
  998.                 wright := right;
  999.                 wbottom := bottom;
  1000.             end;
  1001.         while Button do begin
  1002.                 GetMouse(finish);
  1003.                 with finish do begin
  1004.                         if h < 0 then
  1005.                             h := 0;
  1006.                         if v < 0 then
  1007.                             v := 0;
  1008.                         if h > wright then
  1009.                             h := wright;
  1010.                         if v > wbottom then
  1011.                             v := wbottom;
  1012.                         if (xCoordinates^[nCoordinates] <> h) or (yCoordinates^[nCoordinates] <> v) then begin
  1013.                                 if nCoordinates < MaxCoordinates then
  1014.                                     nCoordinates := nCoordinates + 1
  1015.                                 else
  1016.                                     beep;
  1017.                                 LineTo(h, v);
  1018.                                 xCoordinates^[nCoordinates] := h;
  1019.                                 yCoordinates^[nCoordinates] := v;
  1020.                                 wait(1);
  1021.                             end; {if mouse has moved}
  1022.                     end; {with}
  1023.             end; {while Button}
  1024.     end;
  1025.  
  1026.  
  1027.     procedure DoPolygon (start: point);
  1028.         var
  1029.             Finish, OldFinish: point;
  1030.             finished, DoubleClick, done: boolean;
  1031.             ticks, MouseUpTime, LastMouseUpTime: LongInt;
  1032.             wright, wbottom: integer;
  1033.             StartRect: rect;
  1034.             MouseDown, MouseUpEvent: boolean;
  1035.     begin
  1036.         DrawLabels('DX:', 'DY:', 'Length:');
  1037.         SetPort(info^.wptr);
  1038.         PenMode(PatXor);
  1039.         PenSize(1, 1);
  1040.         if CurrentTool = PolygonTool then begin
  1041.                 Pt2Rect(Start, Start, StartRect);
  1042.                 InsetRect(StartRect, -4, -4);
  1043.                 FrameRect(StartRect);
  1044.             end
  1045.         else
  1046.             SetRect(StartRect, 0, 0, 0, 0);
  1047.         finish := start;
  1048.         finished := false;
  1049.         with info^.wptr^.PortRect do begin
  1050.                 wright := right;
  1051.                 wbottom := bottom;
  1052.             end;
  1053.         MouseUpTime := 0;
  1054.         done := false;
  1055.         MouseUpEvent := false;
  1056.         MouseDown := button;
  1057.         repeat
  1058.             ShowDxDy(0, 0);
  1059.             repeat
  1060.                 OldFinish := finish;
  1061.                 GetMouse(finish);
  1062.                 with finish do begin
  1063.                         if h < 0 then begin
  1064.                                 h := 0;
  1065.                                 done := CurrentTool = LineTool;
  1066.                             end;
  1067.                         if v < 0 then begin
  1068.                                 v := 0;
  1069.                                 done := CurrentTool = LineTool;
  1070.                             end;
  1071.                         if h > wright then begin
  1072.                                 h := wright;
  1073.                                 done := CurrentTool = LineTool;
  1074.                             end;
  1075.                         if v > wbottom then begin
  1076.                                 v := wbottom;
  1077.                                 done := CurrentTool = LineTool;
  1078.                             end;
  1079.                     end;
  1080.                 if not EqualPt(finish, OldFinish) then begin
  1081.                         ticks := TickCount;
  1082.                         repeat
  1083.                         until TickCount <> ticks;
  1084.                         MoveTo(start.h, start.v);
  1085.                         LineTo(OldFinish.h, OldFinish.v);
  1086.                         MoveTo(start.h, start.v);
  1087.                         LineTo(finish.h, finish.v);
  1088.                         ShowDxDy(abs(finish.h - start.h), abs(finish.v - start.v));
  1089.                     end;
  1090.                 if button <> MouseDown then begin
  1091.                         MouseUpEvent := not button;
  1092.                         MouseDown := button;
  1093.                     end;
  1094.             until MouseUpEvent;
  1095.             MouseUpEvent := false;
  1096.             LastMouseUpTime := MouseUpTime;
  1097.             MouseUpTime := TickCount;
  1098.             DoubleClick := ((MouseUpTime - LastMouseUpTime) < GetDblTime) and EqualPt(start, finish);
  1099.             if nCoordinates < MaxCoordinates then
  1100.                 nCoordinates := nCoordinates + 1
  1101.             else
  1102.                 beep;
  1103.             xCoordinates^[nCoordinates] := finish.h;
  1104.             yCoordinates^[nCoordinates] := finish.v;
  1105.             start := finish;
  1106.             Finished := (PtInRect(finish, StartRect) or DoubleClick or done) and (nCoordinates > 2);
  1107.         until finished;
  1108.         FlushEvents(EveryEvent, 0);
  1109.     end;
  1110.  
  1111.  
  1112.     procedure MakePolygon (event: EventRecord);
  1113.         var
  1114.             Start: point;
  1115.             i: integer;
  1116.     begin
  1117.         with info^ do begin
  1118.                 start := event.where;
  1119.                 SetPort(wptr);
  1120.                 PenNormal;
  1121.                 xCoordinates^[1] := Start.h;
  1122.                 yCoordinates^[1] := Start.v;
  1123.                 nCoordinates := 1;
  1124.                 MoveTo(start.h, start.v);
  1125.                 case CurrentTool of
  1126.                     FreehandTool:  begin
  1127.                             DoFreehand;
  1128.                             with Start do
  1129.                                 LineTo(h, v);
  1130.                         end;
  1131.                     PolygonTool: 
  1132.                         DoPolygon(start);
  1133.                 end;
  1134.                 if nCoordinates > 2 then begin
  1135.                         ConvertCoordinates;
  1136.                         if CurrentTool = PolygonTool then
  1137.                             MakeOutline(PolygonRoi)
  1138.                         else
  1139.                             MakeOutline(FreehandRoi);
  1140.                     end
  1141.                 else begin
  1142.                         KillRoi;
  1143.                         UpdatePicWindow;
  1144.                     end;
  1145.             end; {with}
  1146.     end;
  1147.  
  1148.  
  1149.     procedure MakeLineRoi (event: EventRecord);
  1150.         var
  1151.             Start: point;
  1152.     begin
  1153.         if NoUndo then
  1154.             exit(MakeLineRoi);
  1155.         start := event.where;
  1156.         with Info^ do begin
  1157.                 WhatToUndo := NothingToUndo;
  1158.                 measuring := false;
  1159.                 if LOIType = Straight then begin
  1160.                         DoObject(LineObj, event);
  1161.                         RoiType := LineRoi;
  1162.                         MakeRegion;
  1163.                         RoiShowing := true;
  1164.                         SetupUndo;
  1165.                         exit(MakeLineRoi);
  1166.                     end;
  1167.                 SetPort(wptr);
  1168.                 PenNormal;
  1169.                 MoveTo(start.h, start.v);
  1170.                 xCoordinates^[1] := Start.h;
  1171.                 yCoordinates^[1] := Start.v;
  1172.                 nCoordinates := 1;
  1173.             end; {with info}
  1174.         if LOIType = Freehand then
  1175.             DoFreehand
  1176.         else
  1177.             DoPolygon(start);
  1178.         if nCoordinates > 1 then
  1179.             case LoiType of
  1180.                 freehand: 
  1181.                     MakeNonStraightLineRoi(FreeLineRoi);
  1182.                 segmented: 
  1183.                     MakeNonStraightLineRoi(SegLineRoi);
  1184.             end
  1185.         else
  1186.             with info^ do begin
  1187.                     RoiShowing := false;
  1188.                     RoiType := NoRoi;
  1189.                     UpdatePicWindow;
  1190.                 end;
  1191.     end;
  1192.  
  1193.  
  1194.     procedure DoProfilePlot (event: EventRecord);
  1195.         var
  1196.             ulength, clength: extended;
  1197.     begin
  1198.         with Info^ do begin
  1199.                 WhatToUndo := NothingToUndo;
  1200.                 measuring := false;
  1201.                 DoObject(LineObj, event);
  1202.                 RoiType := LineRoi;
  1203.                 MakeRegion;
  1204.                 RoiShowing := true;
  1205.                 SetupUndo;
  1206.                 GetLengthOrPerimeter(ulength, clength);
  1207.                 if ulength > 0 then
  1208.                     PlotDensityProfile
  1209.             end;
  1210.     end;
  1211.  
  1212.  
  1213.     procedure DoMouseDownInWindow (event: EventRecord; WhichWindow: WindowPtr);
  1214.   {Handles mouse down events in the content region of image windows.}
  1215.         var
  1216.             r: rect;
  1217.             str: str255;
  1218.             hloc, vloc: integer;
  1219.             tool: ToolType;
  1220.             start: Point;
  1221.     begin
  1222.         SetPort(info^.wptr);
  1223.         if Digitizing then
  1224.             if (CurrentTool <> MagnifyingGlass) and (CurrentTool <> Grabber) then
  1225.                 StopDigitizing;
  1226.         GlobalToLocal(event.where);
  1227.         IsInsertionPoint := false;
  1228.         with info^ do
  1229.             if RoiShowing then
  1230.                 if EqualRect(RoiRect, PicRect) and (SelectionMode = NewSelection) then {if Select All}
  1231.                     if not (OpPending and (CurrentOp = PasteOp)) then begin
  1232.                             KillRoi;
  1233.                             MouseState := NotInRoi;
  1234.                             exit(DoMouseDownInWindow);
  1235.                         end;
  1236.         if MouseState <> NotInRoi then
  1237.             exit(DoMouseDownInWindow);
  1238.         if SpaceBarDown and (CurrentTool <> TextTool) then
  1239.             tool := grabber
  1240.         else
  1241.             tool := CurrentTool;
  1242.         if (SelectionMode = NewSelection) and not ((tool = MagnifyingGlass) or (tool = Grabber)) then
  1243.             KillRoi;
  1244.         SetupUndo;
  1245.         case tool of
  1246.             SelectionTool: 
  1247.                 DoObject(SelectionRect, event);
  1248.             PolygonTool, FreehandTool: 
  1249.                 MakePolygon(event);
  1250.             OvalSelectionTool: 
  1251.                 DoObject(SelectionOval, event);
  1252.             LineTool: 
  1253.                 MakeLineRoi(event);
  1254.             MagnifyingGlass: 
  1255.                 ZoomIn(event);
  1256.             Grabber: 
  1257.                 Scroll(event);
  1258.             Pencil, Brush, Eraser: 
  1259.                 DoBrush(event);
  1260.             SprayCanTool: 
  1261.                 DoSprayCan;
  1262.             Ruler: 
  1263.                 if OptionKeyDown or ControlKeyDown then
  1264.                     PutError('Use the line selection tool and Measure to measure path lengths.')
  1265.                 else begin
  1266.                         DoObject(LineObj, event);
  1267.                         WhatToUndo := UndoEdit;
  1268.                     end;
  1269.             PaintBucket: 
  1270.                 DoFill(event);
  1271.             TextTool: 
  1272.                 DoText(event.where);
  1273.             PlotTool: 
  1274.                 DoProfilePlot(event);
  1275.             PickerTool: 
  1276.                 if BitAnd(Event.modifiers, OptionKey) = OptionKey then
  1277.                     GetBackgroundColor(event)
  1278.                 else
  1279.                     GetForegroundColor(event);
  1280.             CrossHairTool: 
  1281.                 DoPoints(event);
  1282.             AngleTool: 
  1283.                 FindAngle(event);
  1284.             Wand:  begin
  1285.                     if Digitizing then
  1286.                         StopDigitizing;
  1287.                     start := event.where;
  1288.                     ScreenToOffscreen(start);
  1289.                     AutoOutline(start);
  1290.                 end;
  1291.             otherwise
  1292.                 beep;
  1293.         end;
  1294.     end;
  1295.  
  1296.  
  1297.     procedure DoPopupMenusInTools;
  1298.         var
  1299.             Item: integer;
  1300.             ticks: LongInt;
  1301.  
  1302.         procedure DrawCurrentTool;
  1303.         begin
  1304.             InvalRect(ToolRect[CurrentTool]);
  1305.             BeginUpdate(ToolWindow);
  1306.             DrawTools;
  1307.             EndUpdate(ToolWindow);
  1308.         end;
  1309.  
  1310.     begin
  1311.         DrawCurrentTool;
  1312.         ticks := TickCount;
  1313.         repeat
  1314.         until (not button) or (TickCount > ticks + 20);
  1315.         if button and (TickCount > (ticks + 20)) then
  1316.             with ToolRect[CurrentTool] do begin
  1317.                     Item := PopUpMenu(LineToolMenuH, left, top, ord(LOIType) + 1);
  1318.                     case Item of
  1319.                         1: 
  1320.                             LOIType := Straight;
  1321.                         2: 
  1322.                             LOIType := Freehand;
  1323.                         3: 
  1324.                             LOIType := Segmented;
  1325.                         otherwise
  1326.                     end;
  1327.                     DrawCurrentTool;
  1328.                 end;
  1329.     end;
  1330.  
  1331.  
  1332.     procedure DoMouseDownInTools (loc: point);
  1333.  {Handles mouse down events in the tool palette.}
  1334.         var
  1335.             r: rect;
  1336.             OddTool, DoubleClick: boolean;
  1337.             ToolNum, i: integer;
  1338.     begin
  1339.         SetPort(ToolWindow);
  1340.         GlobalToLocal(loc);
  1341.         if loc.v <= StartOfLines then begin
  1342.                 PreviousTool := CurrentTool;
  1343.                 OddTool := loc.h < tmiddle;
  1344.                 ToolNum := (loc.v div tmiddle) * 2;
  1345.                 if not OddTool then
  1346.                     ToolNum := ToolNum + 1;
  1347.                 CurrentTool := ToolType(ToolNum);
  1348.                 isSelectionTool := (CurrentTool = SelectionTool) or (CurrentTool = OvalSelectionTool) or (CurrentTool = PolygonTool) or (CurrentTool = FreehandTool) or (CurrentTool = LineTool);
  1349.                 DoubleClick := (TickCount - ToolTime) < GetDblTime;
  1350.                 ToolTime := TickCount;
  1351.                 InvalRect(ToolRect[CurrentTool]);
  1352.                 InvalRect(ToolRect[PreviousTool]);
  1353.                 IsInsertionPoint := false;
  1354.                 if DoubleClick and (CurrentTool = PreviousTool) then
  1355.                     case CurrentTool of
  1356.                         MagnifyingGlass: 
  1357.                             Unzoom;
  1358.                         SelectionTool:  begin
  1359.                                 StopDigitizing;
  1360.                                 SelectAll(true);
  1361.                             end;
  1362.                         SprayCanTool: 
  1363.                             SetSprayCanSize;
  1364.                         Brush: 
  1365.                             SetBrushSize;
  1366.                         LineTool: 
  1367.                             SetScale;
  1368.                         PolygonTool: 
  1369.                             DoMeasurementOptions;
  1370.                         FreehandTool: 
  1371.                             Calibrate;
  1372.                         ruler: 
  1373.                             SetLineWidth;
  1374.                         PlotTool: 
  1375.                             DoProfilePlotOptions;
  1376.                         Eraser: 
  1377.                             if info <> NoInfo then begin
  1378.                                     KillRoi;
  1379.                                     SetupUndo;
  1380.                                     WhatToUndo := UndoClear;
  1381.                                     StopDigitizing;
  1382.                                     SelectAll(false);
  1383.                                     DoOperation(eraseOp);
  1384.                                 end;
  1385.                         LutTool, Wand: 
  1386.                             if DensitySlicing then
  1387.                                 DisableDensitySlice
  1388.                             else begin
  1389.                                     if Info^.Thresholding then
  1390.                                         ResetGrayMap;
  1391.                                     if OptionKeyDown then
  1392.                                         AutoDensitySlice;
  1393.                                     EnableDensitySlice;
  1394.                                 end;
  1395.                         PickerTool: 
  1396.                             if info^.LutMode <> PseudoColor then begin  {Switch to pseudocolor mode}
  1397.                                     DisableDensitySlice;
  1398.                                     UpdateLUT;
  1399.                                     CurrentTool := LutTool;
  1400.                                     isSelectionTool := false;
  1401.                                     InvalRect(ToolRect[CurrentTool]);
  1402.                                 end
  1403.                             else
  1404.                                 ResetGrayMap;
  1405.                         otherwise
  1406.                     end; {case}
  1407.                 if (not isSelectionTool) and (CurrentTool <> MagnifyingGlass) and (CurrentTool <> Grabber) and (CurrentTool <> Wand) then
  1408.                     KillRoi;
  1409.                 if not DoubleClick and (CurrentTool = LineTool) then
  1410.                     KillRoi;
  1411.                 with info^ do
  1412.                     if RoiShowing then
  1413.                         if EqualRect(RoiRect, PicRect) and not isSelectionTool then {if Select All}
  1414.                             KillRoi;
  1415.                 if (CurrentTool = SelectionTool) or (CurrentTool = CrossHairTool) then begin
  1416.                         InfoMessage := '';
  1417.                         if mCount > 0 then
  1418.                             ShowInfo;
  1419.                     end;
  1420.                 RoiMode := MoveMode;
  1421.                 if CurrentTool = LineTool then begin
  1422.                         if Button then
  1423.                             DoPopUpMenusInTools;
  1424.                         if (LoiType = Straight) and (LineWidth <> 1) then begin
  1425.                                 LineWidth := 1;
  1426.                                 UpdateRoiLineWidth;
  1427.                                 ShowLineWidth;
  1428.                             end;
  1429.                     end;
  1430.             end
  1431.         else begin
  1432.                 for i := 1 to nLineTypes do begin
  1433.                         r := lines[i];
  1434.                         with r do begin
  1435.                                 left := left - 13;
  1436.                                 top := top - 2;
  1437.                                 right := right + 2;
  1438.                                 bottom := bottom + 2;
  1439.                             end;
  1440.                         if i = 1 then
  1441.                             with r do
  1442.                                 top := top - 7;
  1443.                         if PtInRect(loc, r) then begin
  1444.                                 with lines[i] do
  1445.                                     LineWidth := bottom - top;
  1446.                                 LineIndex := i;
  1447.                             end;
  1448.                     end;
  1449.                 EraseRect(CheckRect);
  1450.                 InvalRect(CheckRect);
  1451.                 UpdateRoiLineWidth;
  1452.             end;
  1453.     end;
  1454.  
  1455.  
  1456.     procedure ScaleToFitScreen;
  1457.         var
  1458.             trect: rect;
  1459.             ignore: boolean;
  1460.     begin
  1461.         with info^ do begin
  1462.                 MoveWindow(wptr, PicLeftBase, PicTopBase, true);
  1463.                 SetRect(trect, 0, 0, ScreenWidth, ScreenHeight);
  1464.                 ScaleImageWindow(trect);
  1465.                 wrect := trect;
  1466.                 SizeWindow(wptr, trect.right, trect.bottom, true);
  1467.             end;
  1468.     end;
  1469.  
  1470.  
  1471.     procedure DoDrag (WhichWindow: WindowPtr; loc: point);
  1472.         var
  1473.             WinRect, DragBounds, trect: rect;
  1474.             kind: integer;
  1475.     begin
  1476.         kind := WindowPeek(WhichWindow)^.WindowKind;
  1477.         if kind = PicKind then begin
  1478.                 with info^ do begin  {Save window location}
  1479.                         GetWindowRect(wptr, trect);
  1480.                         savehloc := trect.left;
  1481.                         savevloc := trect.top;
  1482.                     end;
  1483.                 PicLeft := PicLeftBase;
  1484.                 PicTop := PicTopBase;
  1485.             end;
  1486.         DragBounds := qd.ScreenBits.bounds;
  1487.         DragWindow(WhichWindow, loc, DragBounds);
  1488.         if (info^.PictureType = FrameGrabberType) or OptionKeyDown then begin
  1489.                 GetWindowRect(WhichWindow, trect);
  1490.                 MoveWindow(WhichWindow, band(trect.left, $fffc), trect.top, true);
  1491.             end;
  1492.         if WhichWindow = InfoWindow then
  1493.             ShowInfo;
  1494.         if WhichWindow = ResultsWindow then begin
  1495.                 GetWindowRect(WhichWindow, trect);
  1496.                 ResultsTop := trect.top;
  1497.                 ResultsLeft := trect.left;
  1498.             end;
  1499.     end;
  1500.  
  1501.  
  1502.     procedure UpdateMenus;
  1503.     begin
  1504.         OptionKeyWasDown := OptionKeyDown;
  1505.         CurrentKind := CurrentWindow;
  1506.         UpdateFileMenu;
  1507.         UpdateEditMenu;
  1508.         UpdateOptionsMenu;
  1509.         UpdateTextItems;
  1510.         UpdateProcessMenu;
  1511.         UpdateAnalysisMenu;
  1512.         UpdateSpecialMenu;
  1513.         UpdateStacksMenu;
  1514.         UpdateWindowsMenu;
  1515.     end;
  1516.  
  1517.  
  1518.     function BalloonHelp: boolean;
  1519.     begin
  1520.         if not System7 then begin
  1521.                 BalloonHelp := false;
  1522.                 exit(BalloonHelp);
  1523.             end;
  1524.         BalloonHelp := HMGetBalloons;
  1525.     end;
  1526.  
  1527.  
  1528.     procedure DoMouseDown (event: EventRecord);
  1529.     {Handle mouse-down events}
  1530.         var
  1531.             WhichWindow: WindowPtr;
  1532.             ThePart, ignore, kind: integer;
  1533.             trect: rect;
  1534.     begin
  1535.         ThePart := FindWindow(event.where, WhichWindow);
  1536.         case ThePart of
  1537.             InDesk: 
  1538.                 ;
  1539.             InMenuBar:  begin
  1540.                     UpdateMenus;
  1541.                     DoMenuEvent(MenuSelect(event.where));
  1542.                 end;
  1543.             InSysWindow: 
  1544.                 SystemClick(Event, WhichWindow);
  1545.             InContent:  begin
  1546.             {The Tools, Map, LUT and PasteControl windows do not have
  1547.             to be activated to process the mouse-down event.}
  1548.                     RoiUpdateTime := 0;
  1549.                     if WhichWindow = ToolWindow then begin
  1550.                             if BalloonHelp then
  1551.                                 SelectWindow(ToolWindow);
  1552.                             DoMouseDownInTools(event.where);
  1553.                             exit(DoMouseDown);
  1554.                         end;
  1555.                     if WhichWindow = MapWindow then begin
  1556.                             if BalloonHelp then
  1557.                                 SelectWindow(MapWindow);
  1558.                             DoMouseDownInMap;
  1559.                             exit(DoMouseDown)
  1560.                         end;
  1561.                     if WhichWindow = LUTWindow then begin
  1562.                             if BalloonHelp then
  1563.                                 SelectWindow(LUTWindow);
  1564.                             DoMouseDownInLUT(event);
  1565.                             exit(DoMouseDown)
  1566.                         end;
  1567.                     if WhichWindow = PasteControl then begin
  1568.                             DoMouseDownInPasteControl(event.where);
  1569.                             exit(DoMouseDown)
  1570.                         end;
  1571.                     if WhichWindow <> FrontWindow then begin
  1572.                         {Image windows, text windows and the Result window
  1573.                          must be activated if they are not the current window.}
  1574.                         SelectWindow(WhichWindow);
  1575.                         exit(DoMouseDown);
  1576.                     end;
  1577.                     if WhichWindow = ResultsWindow then begin
  1578.                             DoMouseDownInResults(event.where);
  1579.                             exit(DoMouseDown)
  1580.                         end;
  1581.                     kind := WindowPeek(WhichWindow)^.WindowKind;
  1582.                     if Kind = TextKind then begin
  1583.                             DoMouseDownInText(Event, WhichWindow);
  1584.                             exit(DoMouseDown)
  1585.                         end;
  1586.                     if kind = PicKind then
  1587.                         DoMouseDownInWindow(Event, WhichWindow);
  1588.                 end;
  1589.             InDrag: 
  1590.                 DoDrag(WhichWindow, event.where);
  1591.             InGrow: 
  1592.                 DoGrow(WhichWindow, event);
  1593.             InGoAway: 
  1594.                 if TrackGoAway(WhichWindow, event.where) then
  1595.                     if OptionKeyDown and (CurrentWindow = PicKind) then
  1596.                         CloseAll
  1597.                     else begin
  1598.                             if WhichWindow <> VideoControl then
  1599.                                 StopDigitizing;
  1600.                             ignore := CloseAWindow(WhichWindow);
  1601.                         end;
  1602.             InZoomIn, InZoomOut: 
  1603.                 with info^ do
  1604.                     case WindowState of
  1605.                         NormalWindow:  begin
  1606.                                 if digitizing then
  1607.                                     exit(DoMouseDown);
  1608.                                 ScaleToFit;
  1609.                                 if ScaleToFitWindow then
  1610.                                     ScaleToFitScreen;
  1611.                             end;
  1612.                         TiledSmall, TiledSmallScaled:  begin
  1613.                                 if WindowState = TiledSmall then begin
  1614.                                         ScaleToFitWindow := true;
  1615.                                         WindowState := TiledBig;
  1616.                                     end
  1617.                                 else
  1618.                                     WindowState := TiledBigScaled;
  1619.                                 savewrect := wrect;
  1620.                                 SaveSrcRect := SrcRect;
  1621.                                 SaveMagnification := magnification;
  1622.                                 GetWindowRect(wptr, trect);
  1623.                                 savehloc := trect.left;
  1624.                                 savevloc := trect.top;
  1625.                                 ScaleToFitScreen;
  1626.                                 UpdatePicWindow;
  1627.                             end;
  1628.                         TiledBig:  begin
  1629.                                 ScaleToFitWindow := false;
  1630.                                 WindowState := TiledSmall;
  1631.                                 wrect := savewrect;
  1632.                                 SrcRect := SaveSrcRect;
  1633.                                 magnification := SaveMagnification;
  1634.                                 HideWindow(wptr);
  1635.                                 SizeWindow(wptr, wrect.right, wrect.bottom, true);
  1636.                                 MoveWindow(wptr, savehloc, savevloc, true);
  1637.                                 ShowWindow(wptr);
  1638.                                 UpdatePicWindow;
  1639.                                 magnification := 1.0;
  1640.                                 UpdateTitleBar;
  1641.                             end;
  1642.                         TiledBigScaled:  begin
  1643.                                 WindowState := TiledSmallScaled;
  1644.                                 wrect := savewrect;
  1645.                                 SrcRect := PicRect;
  1646.                                 HideWindow(wptr);
  1647.                                 SizeWindow(wptr, wrect.right, wrect.bottom, true);
  1648.                                 MoveWindow(wptr, savehloc, savevloc, true);
  1649.                                 ShowWindow(wptr);
  1650.                                 UpdatePicWindow;
  1651.                                 if PicRect.right <> 0 then
  1652.                                     magnification := wrect.right / PicRect.right;
  1653.                                 UpdateTitleBar;
  1654.                             end;
  1655.                     end; {case WindowState}
  1656.         end; {case thePart}
  1657.     end;
  1658.  
  1659.  
  1660.     procedure NudgeRoi (key: integer);
  1661.         var
  1662.             dh, dv: integer;
  1663.     begin
  1664.         with info^ do begin
  1665.                 if not RoiShowing then
  1666.                     exit(NudgeRoi);
  1667.                 if OpPending and (CurrentOp <> PasteOp) then begin
  1668.                     KillRoi;
  1669.                     RestoreRoi;
  1670.                 end;
  1671.                 case key of
  1672.                     LeftArrow:  begin
  1673.                             dh := -1;
  1674.                             dv := 0
  1675.                         end;
  1676.                     RightArrow:  begin
  1677.                             dh := 1;
  1678.                             dv := 0
  1679.                         end;
  1680.                     UpArrow:  begin
  1681.                             dh := 0;
  1682.                             dv := -1
  1683.                         end;
  1684.                     DownArrow:  begin
  1685.                             dh := 0;
  1686.                             dv := 1
  1687.                         end;
  1688.                 end;
  1689.                 if OptionKeyDown then begin
  1690.                         if RoiType = RectRoi then
  1691.                             with RoiRect do begin
  1692.                                     right := right + dh;
  1693.                                     if right < left + 2 then
  1694.                                         right := left + 2;
  1695.                                     bottom := bottom + dv;
  1696.                                     if bottom < top + 2 then
  1697.                                         bottom := top + 2;
  1698.                                     MakeRegion;
  1699.                                 end
  1700.                         else
  1701.                             beep;
  1702.                     end
  1703.                 else begin
  1704.                         OffsetRgn(roiRgn, dh, dv);
  1705.                         RoiRect := roiRgn^^.rgnBBox;
  1706.                     end;
  1707.                 RoiNudged := true;
  1708.                 RoiUpdateTime := 0;
  1709.             end;
  1710.     end;
  1711.  
  1712.  
  1713.     procedure DoKeyDown (event: EventRecord);
  1714.         var
  1715.             ch: char;
  1716.             ich, KeyCode: integer;
  1717.     begin
  1718.         Ch := chr(band(Event.message, CharCodeMask));
  1719.         ich := ord(ch);
  1720. {ShowMessage(long2str(ich));}
  1721.         KeyCode := bsr(band(Event.message, KeyCodeMask), 8);
  1722.         if BitAnd(Event.modifiers, CmdKey) = CmdKey then begin
  1723.                 UpdateMenus;
  1724.                 if OptionKeyWasDown then begin
  1725.                         case KeyCode of
  1726.                             1: 
  1727.                                 ch := 'S';
  1728.                             3: 
  1729.                                 ch := 'F';
  1730.                             5: 
  1731.                                 ch := 'G';
  1732.                             8: 
  1733.                                 ch := 'C';
  1734.                             9: 
  1735.                                 ch := 'V';
  1736.                             13: 
  1737.                                 ch := 'W';
  1738.                             17: 
  1739.                                 ch := 'T';
  1740.                             24: 
  1741.                                 ch := '=';
  1742.                             35: 
  1743.                                 ch := 'P';
  1744.                             44: 
  1745.                                 ch := '/';
  1746.                         end;
  1747.                     end;
  1748.                 DoMenuEvent(MenuKey(Ch));
  1749.                 exit(DoKeyDown)
  1750.             end;
  1751.         if CurrentWindow = TextKind then begin
  1752.                 DoKeyDownInText(ch);
  1753.                 exit(DoKeyDown)
  1754.             end;
  1755.         with info^ do
  1756.             if (CurrentTool = TextTool) and IsInsertionPoint and (ord(ch) <> FunctionKey) then
  1757.                 DrawCharacter(ch)
  1758.             else if ch = BackSpace then
  1759.                 DoClear
  1760.             else if RoiShowing and (ich >= LeftArrow) and (ich <= DownArrow) then
  1761.                 NudgeRoi(ich)
  1762.             else if (StackInfo <> nil) and (ch in ['<', ',', chr(PageUp), '>', '.', chr(PageDown), chr(HomeKey), chr(EndKey)]) then begin
  1763.                     if ch in ['<', ',', chr(PageUp)] then
  1764.                         ShowNextSlice(PreviousSliceItem)
  1765.                     else if ch in ['>', '.', chr(PageDown)] then
  1766.                         ShowNextSlice(NextSliceItem)
  1767.                     else if (ich = HomeKey) or (ich = EndKey) then
  1768.                         ShowFirstOrLastSlice(ich);
  1769.                 end
  1770.             else if nMacros > 0 then
  1771.                 RunKeyMacro(ch, KeyCode);
  1772.     end;
  1773.  
  1774.  
  1775.     procedure DoActivate (event: EventRecord);
  1776.         var
  1777.             WhichWindow: WindowPtr;
  1778.             Activating, SwitchingWindows, isOK: boolean;
  1779.             I, kind: integer;
  1780.             NewInfo: InfoPtr;
  1781.     begin
  1782.         WhichWindow := WindowPtr(event.message);
  1783.         kind := WindowPeek(WhichWindow)^.WindowKind;
  1784.         Activating := odd(event.modifiers);
  1785.         case kind of
  1786.             PicKind:  begin
  1787.                     if Activating then begin
  1788.                             NewInfo := pointer(WindowPeek(WhichWindow)^.RefCon);
  1789.                             SwitchingWindows := NewInfo <> Info;
  1790.                             if SwitchingWindows then begin
  1791.                                     StopDigitizing;
  1792.                                     SaveRoi;
  1793.                                     DisableDensitySlice;
  1794.                                 end;
  1795.                             Info := NewInfo;
  1796.                             if SwitchingWindows then
  1797.                                 ActivateWindow;
  1798.                             Measuring := false;
  1799.                             with info^ do begin
  1800.                                     LoadLUT(cTable);
  1801.                                     DrawMap;
  1802.                                     if digitizing and HighlightSaturatedPixels then
  1803.                                         HighlightPixels;
  1804.                                     GenerateValues;
  1805.                                     if fit = uncalibrated then
  1806.                                         DrawLabels('', '', '');
  1807.                                 end; {with}
  1808.                         end
  1809.                     else
  1810.                         KillOperation; {Deactivate}
  1811.                 end;
  1812.             ResultsKind: 
  1813.                 UpdateResultsWindow;
  1814.             TextKind: 
  1815.                 ActivateTextWindow(WhichWindow, Activating);
  1816.             otherwise
  1817.         end; {case}
  1818.         if not activating then begin
  1819.                 WhichWindow := FrontWindow;
  1820.                 if WhichWindow <> nil then begin
  1821.                         kind := WindowPeek(WhichWindow)^.WindowKind;
  1822.                         if kind < 0 then
  1823.                             ConverToSystemClipboard; {DA has become active}
  1824.                     end;
  1825.             end;
  1826.     end;
  1827.  
  1828.  
  1829.     procedure DoUpdate (event: EventRecord);
  1830.         var
  1831.             WhichWindow: WindowPtr;
  1832.             SaveInfo: InfoPtr;
  1833.             kind: integer;
  1834.     begin
  1835.         WhichWindow := WindowPtr(event.message);
  1836.         kind := WindowPeek(WhichWindow)^.WindowKind;
  1837.         BeginUpdate(WhichWindow);
  1838.         case kind of
  1839.             Pickind:  begin
  1840.                     SaveInfo := info;
  1841.                     Info := pointer(WindowPeek(WhichWindow)^.RefCon);
  1842.                     if not digitizing then begin
  1843.                             UpdatePicWindow;
  1844.                             DrawMyGrowIcon(info^.wptr);
  1845.                         end;
  1846.                     info := SaveInfo;
  1847.                 end;
  1848.             ToolKind: 
  1849.                 DrawTools;
  1850.             MapKind: 
  1851.                 DrawMap;
  1852.             LutKind: 
  1853.                 DrawLUT;
  1854.             InfoKind:  begin
  1855.                     DrawLabels('', '', '');
  1856.                     if (mCount > 0) or (InfoMessage <> '') then
  1857.                         ShowInfo;
  1858.                 end;
  1859.             HistoKind: 
  1860.                 DrawHistogram;
  1861.             ProfilePlotKind, CalibrationPlotKind: 
  1862.                 UpdatePlotWindow;
  1863.             ResultsKind: 
  1864.                 UpdateResultsWindow;
  1865.             PasteControlKind: 
  1866.                 DrawPasteControl;
  1867.             TextKind: 
  1868.                 UpdateTextWindow(WhichWindow);
  1869.         end;
  1870.         EndUpdate(WhichWindow);
  1871.     end;
  1872.  
  1873.  
  1874.     procedure DoDiskInsert (event: EventRecord);
  1875. { Process disk insertion event, check for damaged or uninitialized disks. }
  1876.         var
  1877.             p: point;
  1878.             intjunk: integer;
  1879.     begin
  1880.         if (HiWrd(event.message) <> NoErr) then begin
  1881.                 DiLoad;
  1882.                 SetPt(p, 100, 80);
  1883.                 intjunk := DiBadMount(p, event.message);
  1884.                 DiUnload;
  1885.             end;
  1886.     end;
  1887.  
  1888.  
  1889.     procedure DoDialogEvent (event: EventRecord);
  1890.   {Handles modeless dialog box events}
  1891.         var
  1892.             isItemHit: boolean;
  1893.             theDialog: DialogPtr;
  1894.             ItemHit: integer;
  1895.             ch: char;
  1896.     begin
  1897.         if (Event.what = KeyDown) and (BitAnd(Event.modifiers, CmdKey) = CmdKey) then begin
  1898.                 UpdateMenus;
  1899.                 ch := chr(band(Event.message, CharCodeMask));
  1900.                 DoMenuEvent(MenuKey(ch));
  1901.                 exit(DoDialogEvent);
  1902.             end;
  1903.         isItemHit := DialogSelect(event, theDialog, ItemHit);
  1904.         if isItemHit and (theDialog = VideoControl) then
  1905.             DoVideoControl(ItemHit);
  1906.     end;
  1907.  
  1908.  
  1909.     function MyGotRequiredParams(var theAppleEvent:AppleEvent):OSErr;
  1910.     var
  1911.         err:OSErr;
  1912.         returnedType:DescType;
  1913.         actualSize:Size;
  1914.     begin
  1915.         err:=AEGetAttributePtr(theAppleEvent,
  1916.                     keyMissedKeywordAttr, typeWildCard, returnedType,
  1917.                     nil, 0, actualSize);
  1918.         if err=errAEDescNotFound then
  1919.             myGotRequiredParams:=noErr
  1920.         else  if err=noErr then
  1921.             myGotRequiredParams:=errAEParamMissed;
  1922.     end;
  1923.     
  1924.     
  1925.     procedure PrintDocument;
  1926.     begin
  1927.         UpdatePicWindow;
  1928.         WhatToPrint := PrintImage;
  1929.         Print(false);
  1930.         DoClose;
  1931.     end;
  1932.  
  1933.  
  1934. function OpenFinderFile(myFSS:FSSpec; PrintDoc:boolean):OSErr;
  1935. var
  1936.     theInfo: FInfo;
  1937.     err, err1, err2:OSErr;
  1938.     wdRefNum, f:integer;
  1939.     okay:boolean;
  1940. begin
  1941.     OpenFinderFile:=fnfErr;
  1942.     with myFSS do begin
  1943.         err := OpenWD(VRefNum, parID, 0, wdRefNum);
  1944.         if err<>noErr then
  1945.             exit(OpenFinderFile);
  1946.       err := GetFInfo(name, wdRefNum, theInfo);
  1947.         if err<>noErr then
  1948.             exit(OpenFinderFile);
  1949.         okay:=false;
  1950.         OpeningFinderFiles:=true;
  1951.         if theInfo.fdType = 'TIFF' then begin
  1952.             WhatToOpen := OpenTIFF;
  1953.             okay := OpenFile(name, wdRefNum);
  1954.             if OpeningRGB then begin
  1955.                 if okay then
  1956.                     ConvertRGBToEightBitColor(true);
  1957.                 OpeningRGB := false;
  1958.             end;
  1959.             if PrintDoc then
  1960.                 PrintDocument;
  1961.         end;
  1962.         if theInfo.fdType = 'PICT' then begin
  1963.             okay := OpenPICT(name, wdRefNum, false);
  1964.             if PrintDoc then
  1965.                 PrintDocument;
  1966.         end;
  1967.         if theInfo.fdType = 'TEXT' then begin
  1968.             okay := OpenTextFile(name, wdRefNum);
  1969.         end;
  1970.         if theInfo.fdType = 'PICS' then begin
  1971.             okay := OpenPICS(name, wdRefNum);
  1972.           end;
  1973.         if theInfo.fdType = 'Iout' then begin
  1974.             OpenOutline(name, wdRefNum);
  1975.             okay:=true;
  1976.         end;
  1977.         if theInfo.fdType = 'ICOL' then begin
  1978.             OpenColorTable(name, wdRefNum);
  1979.             okay:=true;
  1980.         end;
  1981.           if theInfo.fdType = 'IPIC' then begin
  1982.             WhatToOpen := OpenImage;
  1983.             okay := OpenFile(name, wdRefNum);
  1984.             if PrintDoc then
  1985.                 PrintDocument;
  1986.         end;
  1987.         if theInfo.fdType = 'MooV' then begin
  1988.             okay := OpenQuickTime(name, wdRefNum, true);
  1989.           end;
  1990.         if (theInfo.fdType = 'PREF') or (theInfo.fdType = 'pref') then begin
  1991.             err := fsopen(name, wdRefNum, f);
  1992.             GetPreferences(f);
  1993.             if nExtraColors > 0 then
  1994.                 RedrawLUTWindow;
  1995.             if InvertPixelValues then
  1996.                 InvertGrayLevels;
  1997.         end;
  1998.         OpeningFinderFiles:=false;
  1999.         if okay then
  2000.             OpenFinderFile:=noErr;
  2001.   end;
  2002. end;
  2003.  
  2004.  
  2005. function HandleOpenOrPrint(var theAppleEvent, reply:AppleEvent; RefCon:LongInt; PrintDoc:boolean):OSerr;
  2006.     var
  2007.         err, ignoreErr:OSErr;
  2008.         docList:AEDescList;
  2009.         index, ItemsInList:LongInt;
  2010.         actualSize:Size;
  2011.         keywd:AEKeyword;
  2012.         returnedType:DescType;
  2013.         myFSS:FSSpec;
  2014.     begin
  2015.         err:=AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, docList);
  2016.         if err=noErr then begin
  2017.             err:=myGotRequiredParams(theAppleEvent);
  2018.             if err=noErr then begin
  2019.                 err:=AECountItems(docList, itemsInList);
  2020.                 if err=noErr then
  2021.                     for index:=1 to ItemsInList do begin
  2022.                         err:=AEGetNthPtr(docList, index, typeFSS,
  2023.                                         keywd, returnedType, @myFSS,
  2024.                                         SizeOf(myFSS), actualSize);
  2025.                         if err=noErr then begin
  2026.                             err:=OpenFinderFile(myFSS, PrintDoc);
  2027.                         end;
  2028.                     end;
  2029.             end;
  2030.             ignoreErr:=AEDisposeDesc(docList);
  2031.         end;
  2032.         HandleOpenOrPrint:=err;
  2033.     end;
  2034.     
  2035.     
  2036.     function HandleOpenApp(var theAppleEvent, reply:AppleEvent; RefCon:LongInt):OSerr;
  2037.     begin
  2038.         HandleOpenApp:=noErr;
  2039.     end;
  2040.     
  2041.     
  2042.     function HandleOpenDoc(var theAppleEvent, reply:AppleEvent; RefCon:LongInt):OSerr;
  2043.     begin
  2044.         HandleOpenDoc:=HandleOpenOrPrint(theAppleEvent, reply, RefCon, false);
  2045.     end;
  2046.  
  2047.  
  2048.     function HandlePrintDoc(var theAppleEvent, reply: AppleEvent; RefCon:LongInt):OSerr;
  2049.     begin
  2050.         HandlePrintDoc:=HandleOpenOrPrint(theAppleEvent, reply, RefCon, true);
  2051.     end;
  2052.     
  2053.     function HandleQuit(var theAppleEvent, reply:AppleEvent; RefCon:LongInt):OSerr;
  2054.     begin
  2055.         Finished:=true;
  2056.         HandleQuit:=noErr;
  2057.     end;
  2058.  
  2059.  
  2060.     function HandleEvents: boolean;
  2061.         const
  2062.             mousemovedmessage = $FA;
  2063.             SuspendResumeMessage = 1;
  2064.             ResumeMask = 1;
  2065.         var
  2066.             Event: EventRecord;
  2067.             result: boolean;
  2068.             theDialog: DialogPtr;
  2069.             ItemHit: integer;
  2070.             SleepTicks: LongInt;
  2071.             okay: boolean;
  2072.             err:OSErr;
  2073.     begin
  2074.         if Digitizing then
  2075.             SleepTicks := 0
  2076.         else
  2077.             SleepTicks := 2;
  2078.         if WaitNextEvent(EveryEvent, Event, SleepTicks, nil) then begin
  2079.                 if isDialogEvent(event) then
  2080.                     DoDialogEvent(event)
  2081.                 else
  2082.                     case Event.what of
  2083.                         KeyDown, AutoKey: 
  2084.                             DoKeyDown(Event);
  2085.                         MouseDown: 
  2086.                             DoMouseDown(Event);
  2087.                         ActivateEvt: 
  2088.                             DoActivate(Event);
  2089.                         DiskEvt: 
  2090.                             DoDiskInsert(Event);
  2091.                         UpdateEvt: 
  2092.                             DoUpdate(Event);
  2093.                         osEvt: 
  2094.                             case BSR(event.message, 24) of
  2095.                                 MouseMovedMessage: 
  2096.                                     ;
  2097.                                 SuspendResumeMessage: 
  2098.                                     if BAND(event.message, ResumeMask) <> 0 then begin{Resume event}
  2099.                                             if SwitchLUTOnSuspend and (WhatToUndo = UndoLUT) then begin
  2100.                                                     UndoLUTChange;
  2101.                                                     WhatToUndo := NothingToUndo;
  2102.                                                 end
  2103.                                             else
  2104.                                                 LoadLUT(info^.ctable);
  2105.                                         end
  2106.                                     else begin {Suspend event}
  2107.                                             KillOperation;
  2108.                                             ConverToSystemClipboard;
  2109.                                             if SwitchLUTOnSuspend then begin
  2110.                                                     SetupLUTUndo;
  2111.                                                     okay := LoadCLUTResource(AppleDefaultCLUT);
  2112.                                                 end;
  2113.                                         end;
  2114.                             end;
  2115.                         kHighLevelEvent:
  2116.                                 err:=AEProcessAppleEvent (Event);
  2117.                         otherwise {Do nothing}
  2118.                     end; {case}
  2119.                 HandleEvents := true
  2120.             end
  2121.         else
  2122.             HandleEvents := false;
  2123.     end;
  2124.  
  2125.  
  2126.     procedure ShowInsertionPoint;
  2127.         var
  2128.             tRect: rect;
  2129.             Loc: point;
  2130.             height, imag: integer;
  2131.     begin
  2132.         if (not isInsertionPoint) or (info = NoInfo) then
  2133.             exit(ShowInsertionPoint);
  2134.         if CurrentWindow <> PicKind then
  2135.             exit(ShowInsertionPoint);
  2136.         if (TickCount mod (BlinkTime * 2)) < BlinkTime then
  2137.             exit(ShowInsertionPoint);
  2138.         Loc := InsertionPoint;
  2139.         OffscreenToScreen(loc);
  2140.         with info^, tRect do begin
  2141.                 SetPort(wptr);
  2142.                 imag := trunc(magnification + 0.5);
  2143.                 height := CurrentSize * imag;
  2144.                 height := height - height div 4;
  2145.                 left := loc.h;
  2146.                 bottom := loc.v - imag + 1;
  2147.                 top := bottom - height;
  2148.                 right := left + 1;
  2149.                 PenNormal;
  2150.                 PenSize(imag, imag);
  2151.                 PenMode(PatXor);
  2152.                 FrameRect(tRect);
  2153.                 ipTicks := TickCount + 3;
  2154.                 repeat
  2155.                 until TickCount > ipTicks;
  2156.                 FrameRect(tRect);
  2157.             end;
  2158.     end;
  2159.  
  2160.  
  2161.     procedure UndoRoi;
  2162.         var
  2163.             SrcPtr, DstPtr: ptr;
  2164.             offset, ByteCount, tTop, tBottom: LongInt;
  2165.             tRect: rect;
  2166.     begin
  2167.         with info^ do begin
  2168.                 if PixMapSize <> CurrentUndoSize then
  2169.                     exit(UndoRoi);
  2170.                 tRect := RoiRect;
  2171.                 if RoiType = LineRoi then
  2172.                     InsetRect(tRect, -RoiHandleSize, -RoiHandleSize);
  2173.                 with tRect do begin
  2174.                         tTop := top;
  2175.                         tBottom := bottom;
  2176.                         if tTop < 0 then
  2177.                             tTop := 0;
  2178.                         if tTop > PicRect.bottom then
  2179.                             tTop := PicRect.bottom;
  2180.                         if tBottom < 0 then
  2181.                             tBottom := 0;
  2182.                         if tBottom > PicRect.bottom then
  2183.                             tBottom := PicRect.bottom;
  2184.                     end;
  2185.                 offset := tTop * BytesPerRow;
  2186.                 if offset < 0 then
  2187.                     offset := 0;
  2188.                 SrcPtr := ptr(ord4(UndoBuf) + offset);
  2189.                 DstPtr := ptr(ord4(PicBaseAddr) + offset);
  2190.                 ByteCount := (tBottom - tTop) * BytesPerRow;
  2191.                 BlockMove(SrcPtr, DstPtr, ByteCount);
  2192.             end;
  2193.     end;
  2194.  
  2195.  
  2196.     procedure GetLineHandles (var LeftHandle, MiddleHandle, RightHandle: rect);
  2197.         var
  2198.             offset1, offset2, xcenter, ycenter, x1, y1, x2, y2: integer;
  2199.             rx1, ry1, rx2, ry2: extended;
  2200.     begin
  2201.         offset1 := RoiHandleSize div 2;
  2202.         offset2 := offset1 + 1;
  2203.         GetLoi(rx1, ry1, rx2, ry2);
  2204.         x1 := trunc(rx1);
  2205.         y1 := trunc(ry1);
  2206.         x2 := trunc(rx2);
  2207.         y2 := trunc(ry2);
  2208.         SetRect(LeftHandle, x1 - offset1, y1 - offset1, x1 + offset2, y1 + offset2);
  2209.         with info^.RoiRect do begin
  2210.                 xcenter := left + (right - left) div 2;
  2211.                 ycenter := top + (bottom - top) div 2;
  2212.             end;
  2213.         SetRect(MiddleHandle, xcenter - offset1, ycenter - offset1, xcenter + offset2, ycenter + offset2);
  2214.         SetRect(RightHandle, x2 - offset1, y2 - offset1, x2 + offset2, y2 + offset2);
  2215.     end;
  2216.  
  2217.  
  2218.     procedure DrawROI;
  2219.         var
  2220.             tRect: rect;
  2221.             RoiHandle, LeftHandle, MiddleHandle, RightHandle: rect;
  2222.             psize: integer;
  2223.             StartTicks: LongInt;
  2224.             SaveGDevice: GDHandle;
  2225.     begin
  2226.         with Info^ do begin
  2227.                 StartTicks := TickCount;
  2228.                 if OpPending then
  2229.                     DoOperation(CurrentOp);
  2230.                 SaveGDevice := GetGDevice;
  2231.                 SetGDevice(osGDevice);
  2232.                 SetPort(GrafPtr(Info^.osPort));
  2233.                 PenNormal;
  2234.                 if ScaleToFitWindow then
  2235.                     if (magnification < 1.0) and (magnification <> 0.0) then begin
  2236.                             psize := round(1.0 / magnification + 1.5);
  2237.                             PenSize(psize, psize);
  2238.                         end;
  2239.                 if not ((MouseState = DownInRoi) and OpPending) then
  2240.                     if PixMapSize <= UndoBufSize then begin
  2241.                             pmForeColor(BlackIndex);
  2242.                             pmBackColor(WhiteIndex);
  2243.                             case RoiType of
  2244.                                 RectRoi: 
  2245.                                     with RoiRect do begin
  2246.                                             SetRect(RoiHandle, right - RoiHandleSize, bottom - RoiHandleSize, right, bottom);
  2247.                                             if ((right - left) > RoiHandleSize) and ((bottom - top) > RoiHandleSize) then
  2248.                                                 PaintRect(RoiHandle);
  2249.                                         end;
  2250.                                 LineRoi: 
  2251.                                     if Magnification <= 2.0 then begin
  2252.                                             GetLineHandles(LeftHandle, MiddleHandle, RightHandle);
  2253.                                             PaintRect(LeftHandle);
  2254.                                             if LineWidth < 4 then
  2255.                                                 PaintRect(MiddleHandle);
  2256.                                             PaintRect(RightHandle);
  2257.                                             pmForeColor(WhiteIndex);
  2258.                                             FrameRect(LeftHandle);
  2259.                                             if LineWidth < 4 then
  2260.                                                 FrameRect(MiddleHandle);
  2261.                                             FrameRect(RightHandle);
  2262.                                             pmForeColor(BlackIndex);
  2263.                                         end;
  2264.                                 otherwise
  2265.                             end;
  2266.                             PatIndex := (PatIndex + 1) mod 8;
  2267.                             PenPat(AntPattern[PatIndex]);
  2268.                             FrameRgn(roiRgn);
  2269.                             pmForeColor(ForegroundIndex);
  2270.                             pmBackColor(BackgroundIndex);
  2271.                         end;
  2272.                 if PixMapSize > UndoBufSize then begin
  2273.                         if magnification < 1.0 then
  2274.                             PenSize(2, 2);
  2275.                         PatIndex := (PatIndex + 1) mod 8;
  2276.                         PenPat(AntPattern[PatIndex]);
  2277.                         PenMode(PatXor);
  2278.                         FrameRgn(roiRgn);
  2279.                         if MouseState = DownInRoi then begin
  2280.                                 UnionRect(RoiRect, OldRoiRect, tRect);
  2281.                                 UpdateScreen(tRect);
  2282.                             end
  2283.                         else
  2284.                             UpdateScreen(RoiRect);
  2285.                         FrameRgn(roiRgn);
  2286.                     end
  2287.                 else begin
  2288.                         tRect := RoiRect;
  2289.                         if MouseState = DownInRoi then
  2290.                             UnionRect(RoiRect, OldRoiRect, tRect)
  2291.                         else if RoiNudged then begin
  2292.                                 tRect := RoiRect;
  2293.                                 RoiNudged := false;
  2294.                             end;
  2295.                         if RoiType = LineRoi then
  2296.                             InsetRect(tRect, -RoiHandleSize * 2, -RoiHandleSize * 2)
  2297.                         else
  2298.                             InsetRect(tRect, -2, -2);
  2299.                         UpdateScreen(tRect);
  2300.                         UndoRoi;  {Erase offscreen ROI}
  2301.                     end;
  2302.                 RoiUpdateTime := TickCount - StartTicks;
  2303.             end; {with}
  2304.         SetGDevice(SaveGDevice);
  2305.     end;
  2306.  
  2307.  
  2308.     procedure MoveLineEndPoint (osloc: point);
  2309.         var
  2310.             deltax, deltay: extended;
  2311.     begin
  2312.         with info^, osloc, info^.RoiRect do begin
  2313.                 if h < 0 then
  2314.                     h := 0;
  2315.                 if h > PicRect.right then
  2316.                     h := PicRect.right;
  2317.                 if v < 0 then
  2318.                     v := 0;
  2319.                 if v > PicRect.bottom then
  2320.                     v := PicRect.bottom;
  2321.                 if RoiMode = LeftEndMode then begin
  2322.                         LX1 := h;
  2323.                         LY1 := v;
  2324.                         LX2 := left + LX2;
  2325.                         LY2 := top + LY2;
  2326.                     end
  2327.                 else begin
  2328.                         LX2 := h;
  2329.                         LY2 := v;
  2330.                         LX1 := left + LX1;
  2331.                         LY1 := top + LY1;
  2332.                     end;
  2333.                 if ShiftKeyDown then begin
  2334.                         deltax := LX2 - LX1;
  2335.                         deltay := LY2 - LY1;
  2336.                         if abs(deltax) > abs(deltay) then begin
  2337.                                 if RoiMode = LeftEndMode then
  2338.                                     LY2 := LY1
  2339.                                 else
  2340.                                     LY1 := LY2
  2341.                             end
  2342.                         else begin
  2343.                                 if RoiMode = LeftEndMode then
  2344.                                     LX2 := LX1
  2345.                                 else
  2346.                                     LX1 := LX2
  2347.                             end;
  2348.                     end; {if ShiftKeyDown}
  2349.                 MakeRegion;
  2350.                 osMouseDownLoc := osloc;
  2351.                 RoiUpdateTime := 0;
  2352.                 Show3Values(h, v, MyGetPixel(h, v));
  2353.             end;
  2354.     end;
  2355.  
  2356.  
  2357.     procedure MoveRoi (osloc: point);
  2358.         var
  2359.             dh, dv: integer;
  2360.     begin
  2361.         with info^, info^.RoiRect, osloc do begin
  2362.                 dh := h - osMouseDownLoc.h;
  2363.                 dv := v - osMouseDownLoc.v;
  2364.                 OldRoiRect := RoiRect;
  2365.                 if RoiType = LineRoi then
  2366.                     if (RoiMode = LeftEndMode) or (RoiMode = RightEndMode) then begin
  2367.                             MoveLineEndPoint(osloc);
  2368.                             exit(MoveRoi);
  2369.                         end;
  2370.                 if RoiMode = MoveMode then begin
  2371.                         if RoiMovementState = Constrained then begin
  2372.                                 if dv <> 0 then
  2373.                                     RoiMovementState := ConstrainedV
  2374.                                 else if dh <> 0 then
  2375.                                     RoiMovementState := ConstrainedH
  2376.                             end;
  2377.                         if RoiMovementState = ConstrainedH then
  2378.                             dv := 0
  2379.                         else if RoiMovementState = ConstrainedV then
  2380.                             dh := 0;
  2381.                         if not OpPending then begin
  2382.                                 if left + dh < 0 then
  2383.                                     dh := -left;
  2384.                                 if top + dv < 0 then
  2385.                                     dv := -top;
  2386.                             end;
  2387.                     end;
  2388.                 if not OpPending then begin
  2389.                         if right + dh > PicRect.right then
  2390.                             dh := PicRect.right - right;
  2391.                         if bottom + dv > PicRect.bottom then
  2392.                             dv := PicRect.bottom - bottom;
  2393.                     end;
  2394.                 if RoiMode = StretchMode then begin
  2395.                         measuring := false;
  2396.                         DrawLabels('Width:', 'Height:', '');
  2397.                         if h > left then begin
  2398.                                 right := right + dh;
  2399.                                 if right < (left + 1) then
  2400.                                     right := left + 1;
  2401.                                 if (right - h) > 5 then
  2402.                                     right := h + 2;
  2403.                             end
  2404.                         else
  2405.                             right := left + 1;
  2406.                         if v > top then begin
  2407.                                 bottom := bottom + dv;
  2408.                                 if bottom < (top + 1) then
  2409.                                     bottom := top + 1;
  2410.                                 if (bottom - v) > 5 then
  2411.                                     bottom := v + 2;
  2412.                             end
  2413.                         else
  2414.                             bottom := top + 1;
  2415.                         Show3Values(right - left, bottom - top, -1);
  2416.                         MakeRegion;
  2417.                     end
  2418.                 else begin
  2419.                         OffsetRgn(roiRgn, dh, dv);
  2420.                         Show3Values(left, top, MyGetPixel(left, top));
  2421.                     end;
  2422.                 RoiRect := roiRgn^^.rgnBBox;
  2423.                 osMouseDownLoc := osloc;
  2424.                 RoiUpdateTime := 0; {Forces ROI outline to be redrawn}
  2425.             end; {with Info}
  2426.     end;
  2427.  
  2428.  
  2429.     procedure ShowHistogramValues (GrayLevel: LongInt);
  2430.         var
  2431.             hstart, vstart, ivalue: integer;
  2432.     begin
  2433.         hstart := InfoHStart;
  2434.         vstart := InfoVStart;
  2435.         SetPort(InfoWindow);
  2436.         TextSize(9);
  2437.         TextFont(Monaco);
  2438.         TextMode(SrcCopy);
  2439.         MoveTo(xValueLoc, vstart);
  2440.         with info^ do
  2441.             if fit = uncalibrated then
  2442.                 DrawLong(GrayLevel)
  2443.             else begin
  2444.                     if InvertingCalibrationFunction then
  2445.                         DrawReal(cvalue[255 - GrayLevel], 8, 2)
  2446.                     else
  2447.                         DrawReal(cvalue[GrayLevel], 8, 2);
  2448.                     DrawString(' (');
  2449.                     DrawLong(GrayLevel);
  2450.                     DrawString(' )');
  2451.                 end;
  2452.         DrawString('          ');
  2453.         MoveTo(yValueLoc, vstart + 10);
  2454.         if InvertingCalibrationFunction then
  2455.             DrawLong(histogram[255 - GrayLevel])
  2456.         else
  2457.             DrawLong(histogram[GrayLevel]);
  2458.         DrawString('          ');
  2459.     end;
  2460.  
  2461.  
  2462.     procedure DoPlotCursor (loc: point; kind: integer);
  2463.         var
  2464.             xxscale, angle: extended;
  2465.             xvalue, xinc, yinc: integer;
  2466.             pt: point;
  2467.     begin
  2468.         DrawLabels('X:', 'Y:', '');
  2469.         SetCursor(ToolCursor[SelectionTool]);
  2470.         SetPort(PlotWindow);
  2471.         GlobalToLocal(loc);
  2472.         xxscale := PlotCount / (PlotWidth - PlotRightMargin - PlotLeftMargin);
  2473.         xvalue := trunc((loc.h - PlotLeftMargin) * xxscale);
  2474.         if (xvalue < 0) or (xvalue >= PlotCount) then
  2475.             exit(DoPlotCursor);
  2476.         Show2PlotValues(xvalue, PlotData^[xvalue]);
  2477.         if (kind = CalibrationPlotKind) or (info^.RoiType <> LineRoi) then
  2478.             exit(DoPlotCursor);
  2479.         if button and (info <> NoInfo) then
  2480.             with loc do begin
  2481.                     SetPort(info^.wptr);
  2482.                     PenMode(PatXor);
  2483.                     PenSize(1, 1);
  2484.                     angle := (PlotAngle / 180.0) * pi;
  2485.                     xinc := round(cos(angle) * xvalue);
  2486.                     yinc := round(-sin(angle) * xvalue);
  2487.                     h := PlotStart.h + xinc;
  2488.                     v := PlotStart.v + yinc;
  2489.                     OffscreenToScreen(loc);
  2490.                     MoveTo(h - 7, v);
  2491.                     LineTo(h + 7, v);
  2492.                     MoveTo(h, v - 7);
  2493.                     LineTo(h, v + 7);
  2494.                     wait(2);
  2495.                     MoveTo(h - 7, v);
  2496.                     LineTo(h + 7, v);
  2497.                     MoveTo(h, v - 7);
  2498.                     LineTo(h, v + 7);
  2499.                 end;
  2500.     end;
  2501.  
  2502.  
  2503.     procedure SelectCursor;
  2504.         var
  2505.             loc, osloc, gloc: point;
  2506.             where, kind, i, color, x, y, margin: integer;
  2507.             WhichWindow: WindowPtr;
  2508.             MouseInRoi: boolean;
  2509.             fwptr: WindowPtr;
  2510.             CalValue: extended;
  2511.             RoiStretchHandle, LeftHandle, MiddleHandle, RightHandle: rect;
  2512.             MovingRoi: boolean;
  2513.             pvalue: integer;
  2514.     begin
  2515.         if PasteControl <> nil then begin
  2516.                 fwptr := FrontWindow;
  2517.                 if fwptr <> nil then
  2518.                     if WindowPeek(fwptr)^.WindowKind <> PasteControlKind then
  2519.                         BringToFront(PasteControl);
  2520.             end;
  2521.         SetPort(ScreenPort);
  2522.         GetMouse(gloc);
  2523.         loc := gloc;
  2524.         where := FindWindow(gloc, WhichWindow);
  2525.         if WhichWindow = nil then begin
  2526.                 InitCursor;
  2527.                 exit(SelectCursor)
  2528.             end;
  2529.         kind := WindowPeek(WhichWindow)^.WindowKind;
  2530.         if kind < 0 then
  2531.             exit(SelectCursor); {System Window}
  2532.         if where <> InContent then begin
  2533.                 InitCursor;
  2534.                 exit(SelectCursor)
  2535.             end;
  2536.         case kind of
  2537.             PicKind:  begin
  2538.                     if Info = NoInfo then begin
  2539.                             InitCursor;
  2540.                             exit(SelectCursor)
  2541.                         end;
  2542.                     SetPort(info^.wptr);
  2543.                     GlobalToLocal(loc);
  2544.                     osloc := loc;
  2545.                     ScreenToOffscreen(osloc);
  2546.                     MovingRoi := false;
  2547.                     with info^ do begin
  2548.                             SelectionMode := NewSelection;
  2549.                             if RoiShowing and ((isSelectionTool) or (CurrentTool = Wand)) and (currentTool <> LineTool) then begin
  2550.                                     if OptionKeyDown then
  2551.                                         SelectionMode := SubSelection
  2552.                                     else if ControlKeyDown or (ShiftKeyDown and (CurrentTool <> OvalSelectionTool) and (CurrentTool <> SelectionTool)) then
  2553.                                         SelectionMode := AddSelection;
  2554.                                 end;
  2555.                             if RoiShowing and (SelectionMode = NewSelection) then begin
  2556.                                     MouseInRoi := PtInRgn(osloc, roiRgn);
  2557.                                     if RoiType = LineRoi then begin
  2558.                                             GetLineHandles(LeftHandle, MiddleHandle, RightHandle);
  2559.                                             if magnification <= 2.0 then begin
  2560.                                                     InsetRect(LeftHandle, -2, -2);
  2561.                                                     InsetRect(MiddleHandle, -2, -2);
  2562.                                                     InsetRect(RightHandle, -2, -2);
  2563.                                                 end;
  2564.                                             MouseInRoi := MouseInRoi or PtInRect(osloc, LeftHandle) or MouseInRoi or PtInRect(osloc, MiddleHandle) or MouseInRoi or PtInRect(osloc, RightHandle);
  2565.                                         end;
  2566.                                 end
  2567.                             else
  2568.                                 MouseInRoi := false
  2569.                         end; {with}
  2570.                     if MouseInRoi or (MouseState = DownInRoi) then begin
  2571.                             if MouseState = NotInRoi then
  2572.                                 MouseState := InRoi;
  2573.                             InitCursor;
  2574.                             if button then begin
  2575.                                     if MouseState = InRoi then begin
  2576.                                             if OpPending and (CurrentOp <> PasteOp) then
  2577.                                                 SetupUndo;
  2578.                                             MouseState := DownInRoi;
  2579.                                             osMouseDownLoc := osloc;
  2580.                                             with info^ do
  2581.                                                 case RoiType of
  2582.                                                     RectRoi:  begin
  2583.                                                             if magnification > 1.0 then
  2584.                                                                 margin := 0
  2585.                                                             else
  2586.                                                                 margin := 2;
  2587.                                                             with RoiRect do
  2588.                                                                 SetRect(RoiStretchHandle, right - RoiHandleSize - margin, bottom - RoiHandleSize - margin, right, bottom);
  2589.                                                             if PtInRect(osloc, RoiStretchHandle) then
  2590.                                                                 RoiMode := StretchMode
  2591.                                                             else
  2592.                                                                 RoiMode := MoveMode;
  2593.                                                         end;
  2594.                                                     LineRoi: 
  2595.                                                         if PtInRect(osloc, LeftHandle) then
  2596.                                                             RoiMode := LeftEndMode
  2597.                                                         else if PtInRect(osloc, RightHandle) then
  2598.                                                             RoiMode := RightEndMode
  2599.                                                         else
  2600.                                                             RoiMode := MoveMode;
  2601.                                                     otherwise
  2602.                                                 end; {case}
  2603.                                             if ShiftKeyDown then
  2604.                                                 RoiMovementState := Constrained
  2605.                                             else
  2606.                                                 RoiMovementState := Unconstrained;
  2607.                                         end;
  2608.                                     MoveRoi(osloc);
  2609.                                     MovingRoi := true;
  2610.                                 end
  2611.                             else
  2612.                                 MouseState := InRoi
  2613.                         end
  2614.                     else begin
  2615.                             MouseState := NotInRoi;
  2616.                             if SpaceBarDown and (CurrentTool <> TextTool) then
  2617.                                 SetCursor(ToolCursor[Grabber])
  2618.                             else if (SelectionMode = AddSelection) and (CurrentTool = Wand) then
  2619.                                 SetCursor(WandPlusCursor)
  2620.                             else if (SelectionMode = SubSelection) and (CurrentTool = Wand) then
  2621.                                 SetCursor(WandMinusCursor)
  2622.                             else if SelectionMode = AddSelection then
  2623.                                 SetCursor(CrossPlusCursor)
  2624.                             else if SelectionMode = SubSelection then
  2625.                                 SetCursor(CrossMinusCursor)
  2626.                             else if (CurrentTool = MagnifyingGlass) and OptionKeyDown then
  2627.                                 SetCursor(GlassMinusCursor)
  2628.                             else
  2629.                                 SetCursor(ToolCursor[CurrentTool]);
  2630.                         end;
  2631.                     if not MovingRoi then begin
  2632.                             if isFFT then begin
  2633.                                     DrawLabels('r:', 'theta:', 'Value:');
  2634.                                     with osloc do
  2635.                                         ShowFFTValues(h, v, MyGetPixel(h, v));
  2636.                                     exit(SelectCursor);
  2637.                                 end;
  2638.                             if CurrentTool = PickerTool then
  2639.                                 DrawLabels('X:', 'Y:', 'RGB:')
  2640.                             else
  2641.                                 DrawLabels('X:', 'Y:', 'Value:');
  2642.                             with osloc do begin
  2643.                                     if Digitizing then
  2644.                                         pvalue := GetFGPixel(h, v)
  2645.                                     else
  2646.                                         pvalue := MyGetPixel(h, v);
  2647.                                     Show3Values(h, v, pvalue);
  2648.                                 end;
  2649.                         end;
  2650.                 end;
  2651.             HistoKind:  begin
  2652.                     DrawLabels('Level:', 'Count:', '');
  2653.                     SetCursor(ToolCursor[SelectionTool]);
  2654.                     SetPort(HistoWindow);
  2655.                     GlobalToLocal(loc);
  2656.                     ShowHistogramValues(loc.h);
  2657.                 end;
  2658.             ProfilePlotKind, CalibrationPlotKind: 
  2659.                 DoPlotCursor(loc, kind);
  2660.             LUTKind:  begin
  2661.                     if info^.fit <> uncalibrated then
  2662.                         DrawLabels('Index:', 'Value:', '  RGB:')
  2663.                     else
  2664.                         DrawLabels('Index:', '  RGB:', '');
  2665.                     SetPort(LUTWindow);
  2666.                     GlobalToLocal(loc);
  2667.                     if (CurrentTool = LutTool) or (CurrentTool = Wand) then begin
  2668.                             if loc.v < 256 then
  2669.                                 SetCursor(LUTCursor)
  2670.                             else
  2671.                                 InitCursor
  2672.                         end
  2673.                     else
  2674.                         SetCursor(PickerCursor);
  2675.                     if loc.v < 256 then begin
  2676.                             ShowRGBValues(loc.v);
  2677.                         end
  2678.                     else begin
  2679.                             color := 0;
  2680.                             for i := 1 to nExtraColors + 2 do
  2681.                                 if PtInRect(loc, ExtraColorsRect[i]) then
  2682.                                     Color := ExtraColorsEntry[i];
  2683.                             ShowRGBValues(color);
  2684.                         end;
  2685.                 end;
  2686.             MapKind: 
  2687.                 if OptionKeyDown then
  2688.                     SetCursor(ToolCursor[SelectionTool])
  2689.                 else
  2690.                     SetCursor(gmCursor);
  2691.             TextKind:  begin
  2692.                     TextInfo := TextInfoPtr(WindowPeek(WhichWindow)^.RefCon);
  2693.                     if TextInfo <> nil then
  2694.                         with TextInfo^ do begin
  2695.                                 SetPort(TextWindowPtr);
  2696.                                 GlobalToLocal(loc);
  2697.                                 TEIdle(TextTE);
  2698.                                 with TextWindowPtr^.portRect do begin
  2699.                                         if (loc.h < (right - ScrollBarWidth)) and (loc.v < (bottom - ScrollBarWidth)) then
  2700.                                             SetCursor(ToolCursor[TextTool])
  2701.                                         else
  2702.                                             InitCursor;
  2703.                                     end;
  2704.                             end;
  2705.                 end;
  2706.             otherwise
  2707.                 InitCursor;
  2708.         end; {case}
  2709.     end;
  2710.  
  2711.  
  2712.     procedure CloseAll;
  2713.         var
  2714.             i, j, result: integer;
  2715.             WPeek, NextWPeek: WindowPeek;
  2716.             ignore: boolean;
  2717.     begin
  2718.         InitCursor;
  2719.         WPeek := WindowPeek(FrontWindow);
  2720.         StopDigitizing;
  2721.         while wpeek <> nil do begin
  2722.                 NextWPeek := WPeek^.NextWindow;
  2723.                 case wPeek^.WindowKind of
  2724.                     PicKind:  begin
  2725.                             Info := pointer(WPeek^.RefCon);
  2726.                             result := CloseAWindow(info^.wptr);
  2727.                             if not CommandPeriod then
  2728.                                 for j := 1 to 2 do
  2729.                                     ignore := HandleEvents;
  2730.                             if result = cancel then begin
  2731.                                     ActivateWindow;
  2732.                                     finished := false;
  2733.                                     exit(CloseAll)
  2734.                                 end;
  2735.                         end;
  2736.                     TextKind:  begin
  2737.                             result := CloseAWindow(WindowPtr(wPeek));
  2738.                             if result = cancel then begin
  2739.                                     finished := false;
  2740.                                     exit(CloseAll)
  2741.                                 end;
  2742.                         end;
  2743.                     otherwise
  2744.                         ;
  2745.                 end; {case}
  2746.                 wpeek := NextWPeek;
  2747.             end;
  2748.     end;
  2749.  
  2750.  
  2751.  
  2752.  
  2753.     procedure LoadDefaultMacros;
  2754.   {Looks for a text file named "Image Macros" in the same folder as}
  2755.   {Image, and, if found,  loads the macros contained in it.}
  2756.         var
  2757.             err: OSErr;
  2758.             LaunchRefNum: integer;
  2759.             FinderInfo: FInfo;
  2760.             id: LongInt;
  2761.     begin
  2762.         err := GetVol(nil, LaunchRefNum);
  2763.         if err = noerr then
  2764.             err := GetFInfo('Image Macros', LaunchRefNum, FinderInfo);
  2765.         if err = NoErr then begin
  2766.                 LoadMacrosFromFile('Image Macros', LaunchRefNum);
  2767.                 {$ifc not PowerPC}
  2768.                     UnloadSeg(@LoadMacros);
  2769.                 {$endc}
  2770.             end;
  2771.     end;
  2772.  
  2773.  
  2774.     procedure Shutdown;
  2775.         var
  2776.             AlertID: integer;
  2777.     begin
  2778.         if (UnsavedResults and (mCount > 10)) or (UnsavedResults and (ResultsWindow <> nil)) then begin
  2779.                 InitCursor;
  2780.                 AlertID := alert(500, nil);
  2781.                 if AlertID = CancelResetID then begin
  2782.                         finished := false;
  2783.                         exit(Shutdown)
  2784.                     end;
  2785.             end;
  2786.         CloseAll;
  2787.         if finished then
  2788.             ConverToSystemClipboard;
  2789.     end;
  2790.  
  2791.  
  2792.     procedure InstallEventHandlers;
  2793.     {Installs event handlers for the four required Apple Events.}
  2794.     var
  2795.         err:OSErr;
  2796.     begin
  2797.         err:=AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, NewAEEventHandlerProc(@HandleOpenApp), 0, false);
  2798.         err:=AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, NewAEEventHandlerProc(@HandleOpendoc), 0, false);
  2799.         err:=AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, NewAEEventHandlerProc(@HandlePrintDoc), 0, false);
  2800.         err:=AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, NewAEEventHandlerProc(@HandleQuit), 0, false);
  2801.     end;
  2802.  
  2803.  
  2804. begin
  2805.     Init;
  2806.     InstallEventHandlers;
  2807.     SetupMenus;
  2808.     {GetSettings moved to Init}
  2809.     AllocateBuffers;
  2810.     AllocateArrays;
  2811.     ConvertFromSystemClipboard;
  2812.     LoadDefaultMacros;
  2813.     FindPlugIns;
  2814.     {$ifc not PowerPC}
  2815.         UnloadSeg(@Init);
  2816.     {$endc}
  2817.   {InitUser;} {Uncomment to activate User menu.}
  2818.     repeat
  2819.         if not HandleEvents then
  2820.             if info^.RoiShowing and (RoiUpdateTime < 30) then
  2821.                 DrawRoi;
  2822.         ShowInsertionPoint;
  2823.         SelectCursor;
  2824.         if Digitizing then begin
  2825.                 CaptureAndDisplayFrame;
  2826.                 if ContinuousHistogram then
  2827.                     ShowContinuousHistogram;
  2828.             end;
  2829.         if Finished then
  2830.             Shutdown;
  2831.     until finished;
  2832.     CloseSerialPorts;
  2833.     isOK := LoadCLUTResource(AppleDefaultCLUT);
  2834.     RestoreScreen; {Force Finder to redraw color icons}
  2835. end.